Merge commit '852f2a6343518919e5ca8d3c1bbcab9f493e3cd8'

This commit is contained in:
2024-01-17 17:02:59 +01:00
1244 changed files with 50102 additions and 28146 deletions

View File

@ -0,0 +1,713 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#include "SDL3/SDL.h"
#include "SDL3/SDL_video_capture.h"
#include "../SDL_sysvideocapture.h"
#include "../SDL_video_capture_c.h"
#include "../SDL_pixels_c.h"
#include "../../thread/SDL_systhread.h"
#define DEBUG_VIDEO_CAPTURE_CAPTURE 0
#if defined(__ANDROID__) && __ANDROID_API__ >= 24
/*
* APP_PLATFORM=android-24
* minSdkVersion=24
*
* link with: -lcamera2ndk -lmediandk
*
* AndroidManifest.xml:
* <uses-permission android:name="android.permission.CAMERA"></uses-permission>
* <uses-feature android:name="android.hardware.camera" />
*
*
* Add: #define SDL_VIDEO_CAPTURE 1
* in: include/build_config/SDL_build_config_android.h
*
*
* Very likely SDL must be build with YUV support (done by default)
*
* https://developer.android.com/reference/android/hardware/camera2/CameraManager
* "All camera devices intended to be operated concurrently, must be opened using openCamera(String, CameraDevice.StateCallback, Handler),
* before configuring sessions on any of the camera devices. * "
*/
#include <camera/NdkCameraDevice.h>
#include <camera/NdkCameraManager.h>
#include <media/NdkImage.h>
#include <media/NdkImageReader.h>
#include "../../core/android/SDL_android.h"
static ACameraManager *cameraMgr = NULL;
static ACameraIdList *cameraIdList = NULL;
static void
create_cameraMgr(void)
{
if (cameraMgr == NULL) {
if (!Android_JNI_RequestPermission("android.permission.CAMERA")) {
SDL_SetError("This app doesn't have CAMERA permission");
return;
}
cameraMgr = ACameraManager_create();
if (cameraMgr == NULL) {
SDL_Log("Error creating ACameraManager");
} else {
SDL_Log("Create ACameraManager");
}
}
}
static void
delete_cameraMgr(void)
{
if (cameraIdList) {
ACameraManager_deleteCameraIdList(cameraIdList);
cameraIdList = NULL;
}
if (cameraMgr) {
ACameraManager_delete(cameraMgr);
cameraMgr = NULL;
}
}
struct SDL_PrivateVideoCaptureData
{
ACameraDevice *device;
ACameraCaptureSession *session;
ACameraDevice_StateCallbacks dev_callbacks;
ACameraCaptureSession_stateCallbacks capture_callbacks;
ACaptureSessionOutputContainer *sessionOutputContainer;
AImageReader *reader;
int num_formats;
int count_formats[6]; // see format_2_id
};
/**/
#define FORMAT_SDL SDL_PIXELFORMAT_NV12
static int
format_2_id(int fmt) {
switch (fmt) {
#define CASE(x, y) case x: return y
CASE(FORMAT_SDL, 0);
CASE(SDL_PIXELFORMAT_RGB565, 1);
CASE(SDL_PIXELFORMAT_XRGB8888, 2);
CASE(SDL_PIXELFORMAT_RGBA8888, 3);
CASE(SDL_PIXELFORMAT_RGBX8888, 4);
CASE(SDL_PIXELFORMAT_UNKNOWN, 5);
#undef CASE
default:
return 5;
}
}
static int
id_2_format(int fmt) {
switch (fmt) {
#define CASE(x, y) case y: return x
CASE(FORMAT_SDL, 0);
CASE(SDL_PIXELFORMAT_RGB565, 1);
CASE(SDL_PIXELFORMAT_XRGB8888, 2);
CASE(SDL_PIXELFORMAT_RGBA8888, 3);
CASE(SDL_PIXELFORMAT_RGBX8888, 4);
CASE(SDL_PIXELFORMAT_UNKNOWN, 5);
#undef CASE
default:
return SDL_PIXELFORMAT_UNKNOWN;
}
}
static Uint32
format_android_2_sdl(Uint32 fmt)
{
switch (fmt) {
#define CASE(x, y) case x: return y
CASE(AIMAGE_FORMAT_YUV_420_888, FORMAT_SDL);
CASE(AIMAGE_FORMAT_RGB_565, SDL_PIXELFORMAT_RGB565);
CASE(AIMAGE_FORMAT_RGB_888, SDL_PIXELFORMAT_XRGB8888);
CASE(AIMAGE_FORMAT_RGBA_8888, SDL_PIXELFORMAT_RGBA8888);
CASE(AIMAGE_FORMAT_RGBX_8888, SDL_PIXELFORMAT_RGBX8888);
CASE(AIMAGE_FORMAT_RGBA_FP16, SDL_PIXELFORMAT_UNKNOWN); // 64bits
CASE(AIMAGE_FORMAT_RAW_PRIVATE, SDL_PIXELFORMAT_UNKNOWN);
CASE(AIMAGE_FORMAT_JPEG, SDL_PIXELFORMAT_UNKNOWN);
#undef CASE
default:
SDL_Log("Unknown format AIMAGE_FORMAT '%d'", fmt);
return SDL_PIXELFORMAT_UNKNOWN;
}
}
static Uint32
format_sdl_2_android(Uint32 fmt)
{
switch (fmt) {
#define CASE(x, y) case y: return x
CASE(AIMAGE_FORMAT_YUV_420_888, FORMAT_SDL);
CASE(AIMAGE_FORMAT_RGB_565, SDL_PIXELFORMAT_RGB565);
CASE(AIMAGE_FORMAT_RGB_888, SDL_PIXELFORMAT_XRGB8888);
CASE(AIMAGE_FORMAT_RGBA_8888, SDL_PIXELFORMAT_RGBA8888);
CASE(AIMAGE_FORMAT_RGBX_8888, SDL_PIXELFORMAT_RGBX8888);
#undef CASE
default:
return 0;
}
}
static void
onDisconnected(void *context, ACameraDevice *device)
{
// SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context;
SDL_Log("CB onDisconnected");
}
static void
onError(void *context, ACameraDevice *device, int error)
{
// SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context;
SDL_Log("CB onError");
}
static void
onClosed(void* context, ACameraCaptureSession *session)
{
// SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context;
SDL_Log("CB onClosed");
}
static void
onReady(void* context, ACameraCaptureSession *session)
{
// SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context;
SDL_Log("CB onReady");
}
static void
onActive(void* context, ACameraCaptureSession *session)
{
// SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context;
SDL_Log("CB onActive");
}
int
OpenDevice(SDL_VideoCaptureDevice *_this)
{
camera_status_t res;
/* Cannot open a second camera, while the first one is opened.
* If you want to play several camera, they must all be opened first, then played.
*
* https://developer.android.com/reference/android/hardware/camera2/CameraManager
* "All camera devices intended to be operated concurrently, must be opened using openCamera(String, CameraDevice.StateCallback, Handler),
* before configuring sessions on any of the camera devices. * "
*
*/
if (check_device_playing()) {
return SDL_SetError("A camera is already playing");
}
_this->hidden = (struct SDL_PrivateVideoCaptureData *) SDL_calloc(1, sizeof (struct SDL_PrivateVideoCaptureData));
if (_this->hidden == NULL) {
return SDL_OutOfMemory();
}
create_cameraMgr();
_this->hidden->dev_callbacks.context = (void *) _this;
_this->hidden->dev_callbacks.onDisconnected = onDisconnected;
_this->hidden->dev_callbacks.onError = onError;
res = ACameraManager_openCamera(cameraMgr, _this->dev_name, &_this->hidden->dev_callbacks, &_this->hidden->device);
if (res != ACAMERA_OK) {
return SDL_SetError("Failed to open camera");
}
return 0;
}
void
CloseDevice(SDL_VideoCaptureDevice *_this)
{
if (_this && _this->hidden) {
if (_this->hidden->session) {
ACameraCaptureSession_close(_this->hidden->session);
}
if (_this->hidden->sessionOutputContainer) {
ACaptureSessionOutputContainer_free(_this->hidden->sessionOutputContainer);
}
if (_this->hidden->reader) {
AImageReader_delete(_this->hidden->reader);
}
if (_this->hidden->device) {
ACameraDevice_close(_this->hidden->device);
}
SDL_free(_this->hidden);
_this->hidden = NULL;
}
if (check_all_device_closed()) {
delete_cameraMgr();
}
}
int
InitDevice(SDL_VideoCaptureDevice *_this)
{
size_t size, pitch;
SDL_CalculateSize(_this->spec.format, _this->spec.width, _this->spec.height, &size, &pitch, SDL_FALSE);
SDL_Log("Buffer size: %d x %d", _this->spec.width, _this->spec.height);
return 0;
}
int
GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec)
{
if (spec) {
*spec = _this->spec;
return 0;
}
return -1;
}
int
StartCapture(SDL_VideoCaptureDevice *_this)
{
camera_status_t res;
media_status_t res2;
ANativeWindow *window = NULL;
ACaptureSessionOutput *sessionOutput;
ACameraOutputTarget *outputTarget;
ACaptureRequest *request;
res2 = AImageReader_new(_this->spec.width, _this->spec.height, format_sdl_2_android(_this->spec.format), 10 /* nb buffers */, &_this->hidden->reader);
if (res2 != AMEDIA_OK) {
SDL_SetError("Error AImageReader_new");
goto error;
}
res2 = AImageReader_getWindow(_this->hidden->reader, &window);
if (res2 != AMEDIA_OK) {
SDL_SetError("Error AImageReader_new");
goto error;
}
res = ACaptureSessionOutput_create(window, &sessionOutput);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACaptureSessionOutput_create");
goto error;
}
res = ACaptureSessionOutputContainer_create(&_this->hidden->sessionOutputContainer);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACaptureSessionOutputContainer_create");
goto error;
}
res = ACaptureSessionOutputContainer_add(_this->hidden->sessionOutputContainer, sessionOutput);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACaptureSessionOutputContainer_add");
goto error;
}
res = ACameraOutputTarget_create(window, &outputTarget);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACameraOutputTarget_create");
goto error;
}
res = ACameraDevice_createCaptureRequest(_this->hidden->device, TEMPLATE_RECORD, &request);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACameraDevice_createCaptureRequest");
goto error;
}
res = ACaptureRequest_addTarget(request, outputTarget);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACaptureRequest_addTarget");
goto error;
}
_this->hidden->capture_callbacks.context = (void *) _this;
_this->hidden->capture_callbacks.onClosed = onClosed;
_this->hidden->capture_callbacks.onReady = onReady;
_this->hidden->capture_callbacks.onActive = onActive;
res = ACameraDevice_createCaptureSession(_this->hidden->device,
_this->hidden->sessionOutputContainer,
&_this->hidden->capture_callbacks,
&_this->hidden->session);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACameraDevice_createCaptureSession");
goto error;
}
res = ACameraCaptureSession_setRepeatingRequest(_this->hidden->session, NULL, 1, &request, NULL);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACameraDevice_createCaptureSession");
goto error;
}
return 0;
error:
return -1;
}
int
StopCapture(SDL_VideoCaptureDevice *_this)
{
ACameraCaptureSession_close(_this->hidden->session);
_this->hidden->session = NULL;
return 0;
}
int
AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame)
{
media_status_t res;
AImage *image;
res = AImageReader_acquireNextImage(_this->hidden->reader, &image);
/* We could also use this one:
res = AImageReader_acquireLatestImage(_this->hidden->reader, &image);
*/
if (res == AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE ) {
SDL_Delay(20); // TODO fix some delay
#if DEBUG_VIDEO_CAPTURE_CAPTURE
// SDL_Log("AImageReader_acquireNextImage: AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE");
#endif
return 0;
} else if (res == AMEDIA_OK ) {
int i = 0;
int32_t numPlanes = 0;
AImage_getNumberOfPlanes(image, &numPlanes);
frame->timestampNS = SDL_GetTicksNS();
for (i = 0; i < numPlanes && i < 3; i++) {
int dataLength = 0;
int rowStride = 0;
uint8_t *data = NULL;
frame->num_planes += 1;
AImage_getPlaneRowStride(image, i, &rowStride);
res = AImage_getPlaneData(image, i, &data, &dataLength);
if (res == AMEDIA_OK) {
frame->data[i] = data;
frame->pitch[i] = rowStride;
}
}
if (frame->num_planes == 3) {
/* plane 2 and 3 are interleaved NV12. SDL only takes two planes for this format */
int pixelStride = 0;
AImage_getPlanePixelStride(image, 1, &pixelStride);
if (pixelStride == 2) {
frame->num_planes -= 1;
}
}
frame->internal = (void*)image;
return 0;
} else if (res == AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED) {
SDL_SetError("AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED");
} else {
SDL_SetError("AImageReader_acquireNextImage: %d", res);
}
return -1;
}
int
ReleaseFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame)
{
if (frame->internal){
AImage_delete((AImage *)frame->internal);
}
return 0;
}
int
GetNumFormats(SDL_VideoCaptureDevice *_this)
{
camera_status_t res;
int i;
int unknown = 0;
ACameraMetadata *metadata;
ACameraMetadata_const_entry entry;
if (_this->hidden->num_formats != 0) {
return _this->hidden->num_formats;
}
res = ACameraManager_getCameraCharacteristics(cameraMgr, _this->dev_name, &metadata);
if (res != ACAMERA_OK) {
return -1;
}
res = ACameraMetadata_getConstEntry(metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
if (res != ACAMERA_OK) {
return -1;
}
SDL_Log("got entry ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS");
for (i = 0; i < entry.count; i += 4) {
int32_t format = entry.data.i32[i + 0];
int32_t type = entry.data.i32[i + 3];
Uint32 fmt;
if (type == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
continue;
}
fmt = format_android_2_sdl(format);
_this->hidden->count_formats[format_2_id(fmt)] += 1;
#if DEBUG_VIDEO_CAPTURE_CAPTURE
if (fmt != SDL_PIXELFORMAT_UNKNOWN) {
int w = entry.data.i32[i + 1];
int h = entry.data.i32[i + 2];
SDL_Log("Got format android 0x%08x -> %s %d x %d", format, SDL_GetPixelFormatName(fmt), w, h);
} else {
unknown += 1;
}
#endif
}
#if DEBUG_VIDEO_CAPTURE_CAPTURE
if (unknown) {
SDL_Log("Got unknown android");
}
#endif
if ( _this->hidden->count_formats[0]) _this->hidden->num_formats += 1;
if ( _this->hidden->count_formats[1]) _this->hidden->num_formats += 1;
if ( _this->hidden->count_formats[2]) _this->hidden->num_formats += 1;
if ( _this->hidden->count_formats[3]) _this->hidden->num_formats += 1;
if ( _this->hidden->count_formats[4]) _this->hidden->num_formats += 1;
if ( _this->hidden->count_formats[5]) _this->hidden->num_formats += 1;
return _this->hidden->num_formats;
}
int
GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format)
{
int i;
int i2 = 0;
if (_this->hidden->num_formats == 0) {
GetNumFormats(_this);
}
if (index < 0 || index >= _this->hidden->num_formats) {
return -1;
}
for (i = 0; i < SDL_arraysize(_this->hidden->count_formats); i++) {
if (_this->hidden->count_formats[i] == 0) {
continue;
}
if (i2 == index) {
*format = id_2_format(i);
}
i2++;
}
return 0;
}
int
GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format)
{
int i, i2 = 0, index;
if (_this->hidden->num_formats == 0) {
GetNumFormats(_this);
}
index = format_2_id(format);
for (i = 0; i < SDL_arraysize(_this->hidden->count_formats); i++) {
if (_this->hidden->count_formats[i] == 0) {
continue;
}
if (i2 == index) {
/* number of resolution for this format */
return _this->hidden->count_formats[i];
}
i2++;
}
return -1;
}
int
GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height)
{
camera_status_t res;
int i, i2 = 0;
ACameraMetadata *metadata;
ACameraMetadata_const_entry entry;
if (_this->hidden->num_formats == 0) {
GetNumFormats(_this);
}
res = ACameraManager_getCameraCharacteristics(cameraMgr, _this->dev_name, &metadata);
if (res != ACAMERA_OK) {
return -1;
}
res = ACameraMetadata_getConstEntry(metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
if (res != ACAMERA_OK) {
return -1;
}
for (i = 0; i < entry.count; i += 4) {
int32_t f = entry.data.i32[i + 0];
int w = entry.data.i32[i + 1];
int h = entry.data.i32[i + 2];
int32_t type = entry.data.i32[i + 3];
Uint32 fmt;
if (type == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
continue;
}
fmt = format_android_2_sdl(f);
if (fmt != format) {
continue;
}
if (i2 == index) {
*width = w;
*height = h;
return 0;
}
i2++;
}
return -1;
}
static int GetNumDevices(void);
int
GetDeviceName(SDL_VideoCaptureDeviceID instance_id, char *buf, int size)
{
int index = instance_id - 1;
create_cameraMgr();
if (cameraIdList == NULL) {
GetNumDevices();
}
if (cameraIdList) {
if (index >= 0 && index < cameraIdList->numCameras) {
SDL_snprintf(buf, size, "%s", cameraIdList->cameraIds[index]);
return 0;
}
}
return -1;
}
static int
GetNumDevices(void)
{
camera_status_t res;
create_cameraMgr();
if (cameraIdList) {
ACameraManager_deleteCameraIdList(cameraIdList);
cameraIdList = NULL;
}
res = ACameraManager_getCameraIdList(cameraMgr, &cameraIdList);
if (res == ACAMERA_OK) {
if (cameraIdList) {
return cameraIdList->numCameras;
}
}
return -1;
}
SDL_VideoCaptureDeviceID *GetVideoCaptureDevices(int *count)
{
/* hard-coded list of ID */
int i;
int num = GetNumDevices();
SDL_VideoCaptureDeviceID *ret;
ret = (SDL_VideoCaptureDeviceID *)SDL_malloc((num + 1) * sizeof(*ret));
if (ret == NULL) {
SDL_OutOfMemory();
*count = 0;
return NULL;
}
for (i = 0; i < num; i++) {
ret[i] = i + 1;
}
ret[num] = 0;
*count = num;
return ret;
}
int SDL_SYS_VideoCaptureInit(void) {
return 0;
}
int SDL_SYS_VideoCaptureQuit(void) {
return 0;
}
#endif

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -45,6 +45,7 @@ static void android_egl_context_restore(SDL_Window *window)
if (window) {
SDL_Event event;
SDL_WindowData *data = window->driverdata;
SDL_GL_MakeCurrent(window, NULL);
if (SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context) < 0) {
/* The context is no longer valid, create a new one */
data->egl_context = (EGLContext)SDL_GL_CreateContext(window);
@ -107,7 +108,7 @@ void Android_PumpEvents_Blocking(SDL_VideoDevice *_this)
#endif
ANDROIDAUDIO_PauseDevices();
openslES_PauseDevices();
OPENSLES_PauseDevices();
AAUDIO_PauseDevices();
if (SDL_WaitSemaphore(Android_ResumeSem) == 0) {
@ -118,7 +119,7 @@ void Android_PumpEvents_Blocking(SDL_VideoDevice *_this)
SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND);
ANDROIDAUDIO_ResumeDevices();
openslES_ResumeDevices();
OPENSLES_ResumeDevices();
AAUDIO_ResumeDevices();
/* Restore the GL Context from here, as this operation is thread dependent */
@ -131,8 +132,9 @@ void Android_PumpEvents_Blocking(SDL_VideoDevice *_this)
#endif
/* Make sure SW Keyboard is restored when an app becomes foreground */
if (SDL_TextInputActive()) {
Android_StartTextInput(_this); /* Only showTextInput */
if (SDL_TextInputActive() &&
SDL_GetHintBoolean(SDL_HINT_ENABLE_SCREEN_KEYBOARD, SDL_TRUE)) {
Android_ShowScreenKeyboard(_this, Android_Window); /* Only showTextInput */
}
SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND);
@ -159,11 +161,6 @@ void Android_PumpEvents_Blocking(SDL_VideoDevice *_this)
}
}
}
if (AAUDIO_DetectBrokenPlayState()) {
AAUDIO_PauseDevices();
AAUDIO_ResumeDevices();
}
}
void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this)
@ -186,7 +183,7 @@ void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this)
if (videodata->pauseAudio) {
ANDROIDAUDIO_PauseDevices();
openslES_PauseDevices();
OPENSLES_PauseDevices();
AAUDIO_PauseDevices();
}
@ -202,7 +199,7 @@ void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this)
if (videodata->pauseAudio) {
ANDROIDAUDIO_ResumeDevices();
openslES_ResumeDevices();
OPENSLES_ResumeDevices();
AAUDIO_ResumeDevices();
}
@ -216,8 +213,9 @@ void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this)
#endif
/* Make sure SW Keyboard is restored when an app becomes foreground */
if (SDL_TextInputActive()) {
Android_StartTextInput(_this); /* Only showTextInput */
if (SDL_TextInputActive() &&
SDL_GetHintBoolean(SDL_HINT_ENABLE_SCREEN_KEYBOARD, SDL_TRUE)) {
Android_ShowScreenKeyboard(_this, Android_Window); /* Only showTextInput */
}
SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND);
@ -245,11 +243,6 @@ void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this)
}
}
}
if (AAUDIO_DetectBrokenPlayState()) {
AAUDIO_PauseDevices();
AAUDIO_ResumeDevices();
}
}
#endif /* SDL_VIDEO_DRIVER_ANDROID */

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -341,22 +341,22 @@ SDL_bool Android_HasScreenKeyboardSupport(SDL_VideoDevice *_this)
return SDL_TRUE;
}
void Android_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_VideoData *videodata = _this->driverdata;
Android_JNI_ShowScreenKeyboard(&videodata->textRect);
}
void Android_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window)
{
Android_JNI_HideScreenKeyboard();
}
SDL_bool Android_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window)
{
return Android_JNI_IsScreenKeyboardShown();
}
void Android_StartTextInput(SDL_VideoDevice *_this)
{
SDL_VideoData *videodata = _this->driverdata;
Android_JNI_ShowTextInput(&videodata->textRect);
}
void Android_StopTextInput(SDL_VideoDevice *_this)
{
Android_JNI_HideTextInput();
}
int Android_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect)
{
SDL_VideoData *videodata = _this->driverdata;

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -26,8 +26,7 @@ extern int Android_OnKeyDown(int keycode);
extern int Android_OnKeyUp(int keycode);
extern SDL_bool Android_HasScreenKeyboardSupport(SDL_VideoDevice *_this);
extern void Android_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
extern void Android_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
extern SDL_bool Android_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window);
extern void Android_StartTextInput(SDL_VideoDevice *_this);
extern void Android_StopTextInput(SDL_VideoDevice *_this);
extern int Android_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect);

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -68,10 +68,7 @@ static SDL_Cursor *Android_WrapCursor(int custom_cursor, int system_cursor)
} else {
SDL_free(cursor);
cursor = NULL;
SDL_OutOfMemory();
}
} else {
SDL_OutOfMemory();
}
return cursor;
@ -88,7 +85,7 @@ static SDL_Cursor *Android_CreateCursor(SDL_Surface *surface, int hot_x, int hot
SDL_Surface *converted;
converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888);
if (converted == NULL) {
if (!converted) {
return NULL;
}
custom_cursor = Android_JNI_CreateCustomCursor(converted, hot_x, hot_y);
@ -117,7 +114,7 @@ static void Android_FreeCursor(SDL_Cursor *cursor)
static SDL_Cursor *Android_CreateEmptyCursor()
{
if (empty_cursor == NULL) {
if (!empty_cursor) {
SDL_Surface *empty_surface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ARGB8888);
if (empty_surface) {
SDL_memset(empty_surface->pixels, 0, (size_t)empty_surface->h * empty_surface->pitch);
@ -138,7 +135,7 @@ static void Android_DestroyEmptyCursor()
static int Android_ShowCursor(SDL_Cursor *cursor)
{
if (cursor == NULL) {
if (!cursor) {
cursor = Android_CreateEmptyCursor();
}
if (cursor) {
@ -215,7 +212,7 @@ void Android_OnMouse(SDL_Window *window, int state, int action, float x, float y
int changes;
Uint8 button;
if (window == NULL) {
if (!window) {
return;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -52,7 +52,7 @@ void Android_OnTouch(SDL_Window *window, int touch_device_id_in, int pointer_fin
SDL_TouchID touchDeviceId = 0;
SDL_FingerID fingerId = 0;
if (window == NULL) {
if (!window) {
return;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -86,14 +86,12 @@ static SDL_VideoDevice *Android_CreateDevice(void)
/* Initialize all variables that we clean on shutdown */
device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
if (device == NULL) {
SDL_OutOfMemory();
if (!device) {
return NULL;
}
data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData));
if (data == NULL) {
SDL_OutOfMemory();
if (!data) {
SDL_free(device);
return NULL;
}
@ -117,7 +115,6 @@ static SDL_VideoDevice *Android_CreateDevice(void)
device->MinimizeWindow = Android_MinimizeWindow;
device->SetWindowResizable = Android_SetWindowResizable;
device->DestroyWindow = Android_DestroyWindow;
device->GetWindowWMInfo = Android_GetWindowWMInfo;
device->free = Android_DeleteDevice;
@ -145,12 +142,12 @@ static SDL_VideoDevice *Android_CreateDevice(void)
device->SuspendScreenSaver = Android_SuspendScreenSaver;
/* Text input */
device->StartTextInput = Android_StartTextInput;
device->StopTextInput = Android_StopTextInput;
device->SetTextInputRect = Android_SetTextInputRect;
/* Screen keyboard */
device->HasScreenKeyboardSupport = Android_HasScreenKeyboardSupport;
device->ShowScreenKeyboard = Android_ShowScreenKeyboard;
device->HideScreenKeyboard = Android_HideScreenKeyboard;
device->IsScreenKeyboardShown = Android_IsScreenKeyboardShown;
/* Clipboard */
@ -158,6 +155,8 @@ static SDL_VideoDevice *Android_CreateDevice(void)
device->GetClipboardText = Android_GetClipboardText;
device->HasClipboardText = Android_HasClipboardText;
device->device_caps = VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS;
return device;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -35,7 +35,6 @@
#include "SDL_androidvulkan.h"
#include <SDL3/SDL_syswm.h>
int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path)
{
@ -49,10 +48,10 @@ int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path)
}
/* Load the Vulkan loader library */
if (path == NULL) {
if (!path) {
path = SDL_getenv("SDL_VULKAN_LIBRARY");
}
if (path == NULL) {
if (!path) {
path = "libvulkan.so";
}
_this->vulkan_config.loader_handle = SDL_LoadObject(path);
@ -77,7 +76,7 @@ int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path)
(PFN_vkEnumerateInstanceExtensionProperties)
_this->vulkan_config.vkEnumerateInstanceExtensionProperties,
&extensionCount);
if (extensions == NULL) {
if (!extensions) {
goto fail;
}
for (i = 0; i < extensionCount; i++) {
@ -111,25 +110,22 @@ void Android_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
}
}
SDL_bool Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
unsigned *count,
const char **names)
char const* const* Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count)
{
static const char *const extensionsForAndroid[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
};
if (!_this->vulkan_config.loader_handle) {
SDL_SetError("Vulkan is not loaded");
return SDL_FALSE;
if(count) {
*count = SDL_arraysize(extensionsForAndroid);
}
return SDL_Vulkan_GetInstanceExtensions_Helper(
count, names, SDL_arraysize(extensionsForAndroid),
extensionsForAndroid);
return extensionsForAndroid;
}
SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this,
SDL_Window *window,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface)
{
SDL_WindowData *windowData = window->driverdata;
@ -157,8 +153,7 @@ SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this,
createInfo.pNext = NULL;
createInfo.flags = 0;
createInfo.window = windowData->native_window;
result = vkCreateAndroidSurfaceKHR(instance, &createInfo,
NULL, surface);
result = vkCreateAndroidSurfaceKHR(instance, &createInfo, allocator, surface);
if (result != VK_SUCCESS) {
SDL_SetError("vkCreateAndroidSurfaceKHR failed: %s",
SDL_Vulkan_GetResultString(result));

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -36,12 +36,12 @@
int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path);
void Android_Vulkan_UnloadLibrary(SDL_VideoDevice *_this);
SDL_bool Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
unsigned *count,
const char **names);
char const* const* Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count);
SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this,
SDL_Window *window,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
#endif

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -31,12 +31,11 @@
#include "SDL_androidvideo.h"
#include "SDL_androidwindow.h"
#include <SDL3/SDL_syswm.h>
/* Currently only one window */
SDL_Window *Android_Window = NULL;
int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props)
{
SDL_WindowData *data;
int retval = 0;
@ -62,18 +61,18 @@ int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
SDL_SetKeyboardFocus(window);
data = (SDL_WindowData *)SDL_calloc(1, sizeof(*data));
if (data == NULL) {
retval = SDL_OutOfMemory();
if (!data) {
retval = -1;
goto endfunction;
}
data->native_window = Android_JNI_GetNativeWindow();
if (!data->native_window) {
SDL_free(data);
retval = SDL_SetError("Could not fetch native window");
goto endfunction;
}
SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER, data->native_window);
/* Do not create EGLSurface for Vulkan window since it will then make the window
incompatible with vkCreateAndroidSurfaceKHR */
@ -88,6 +87,7 @@ int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
goto endfunction;
}
}
SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER, data->egl_surface);
#endif
window->driverdata = data;
@ -105,7 +105,7 @@ void Android_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window)
Android_JNI_SetActivityTitle(window->title);
}
void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
int Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
{
SDL_LockMutex(Android_ActivityMutex);
@ -129,7 +129,7 @@ void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL
}
data = window->driverdata;
if (data == NULL || !data->native_window) {
if (!data || !data->native_window) {
if (data && !data->native_window) {
SDL_SetError("Missing native window");
}
@ -154,6 +154,7 @@ void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL
endfunction:
SDL_UnlockMutex(Android_ActivityMutex);
return 0;
}
void Android_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
@ -194,18 +195,4 @@ void Android_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
SDL_UnlockMutex(Android_ActivityMutex);
}
int Android_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info)
{
SDL_WindowData *data = window->driverdata;
info->subsystem = SDL_SYSWM_ANDROID;
info->info.android.window = data->native_window;
#ifdef SDL_VIDEO_OPENGL_EGL
info->info.android.surface = data->egl_surface;
#endif
return 0;
}
#endif /* SDL_VIDEO_DRIVER_ANDROID */

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -26,14 +26,13 @@
#include "../../core/android/SDL_android.h"
#include "../SDL_egl_c.h"
extern int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props);
extern void Android_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window);
extern void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
extern int Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
extern void Android_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void Android_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable);
extern void Android_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern int Android_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info);
extern SDL_Window *Android_Window;
struct SDL_WindowData