Atlas - SDL_vitavideo.c

Home / ext / SDL / src / video / vita Lines: 1 | Size: 17218 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21 22#include "SDL_internal.h" 23 24#ifdef SDL_VIDEO_DRIVER_VITA 25 26// SDL internals 27#include "../SDL_sysvideo.h" 28#include "../../events/SDL_mouse_c.h" 29#include "../../events/SDL_keyboard_c.h" 30 31// VITA declarations 32#include <psp2/kernel/processmgr.h> 33#include "SDL_vitavideo.h" 34#include "SDL_vitatouch.h" 35#include "SDL_vitakeyboard.h" 36#include "SDL_vitamouse_c.h" 37#include "SDL_vitaframebuffer.h" 38#include "SDL_vitamessagebox.h" 39 40#if defined(SDL_VIDEO_VITA_PVR) 41#define VITA_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal 42#define VITA_GLES_UnloadLibrary SDL_EGL_UnloadLibrary 43#define VITA_GLES_SetSwapInterval SDL_EGL_SetSwapInterval 44#define VITA_GLES_GetSwapInterval SDL_EGL_GetSwapInterval 45#define VITA_GLES_DestroyContext SDL_EGL_DestroyContext 46#endif 47 48SDL_Window *Vita_Window; 49 50static void VITA_Destroy(SDL_VideoDevice *device) 51{ 52 SDL_free(device->internal); 53 SDL_free(device); 54} 55 56static SDL_VideoDevice *VITA_Create(void) 57{ 58 SDL_VideoDevice *device; 59 SDL_VideoData *phdata; 60#ifdef SDL_VIDEO_VITA_PIB 61 SDL_GLDriverData *gldata; 62#endif 63 // Initialize SDL_VideoDevice structure 64 device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); 65 if (!device) { 66 return NULL; 67 } 68 69 // Initialize internal VITA specific data 70 phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); 71 if (!phdata) { 72 SDL_free(device); 73 return NULL; 74 } 75#ifdef SDL_VIDEO_VITA_PIB 76 77 gldata = (SDL_GLDriverData *)SDL_calloc(1, sizeof(SDL_GLDriverData)); 78 if (!gldata) { 79 SDL_free(device); 80 SDL_free(phdata); 81 return NULL; 82 } 83 device->gl_data = gldata; 84 phdata->egl_initialized = true; 85#endif 86 phdata->ime_active = false; 87 88 device->internal = phdata; 89 90 // Setup amount of available displays and current display 91 device->num_displays = 0; 92 93 // Set device free function 94 device->free = VITA_Destroy; 95 96 // Setup all functions which we can handle 97 device->VideoInit = VITA_VideoInit; 98 device->VideoQuit = VITA_VideoQuit; 99 device->CreateSDLWindow = VITA_CreateWindow; 100 device->SetWindowTitle = VITA_SetWindowTitle; 101 device->SetWindowPosition = VITA_SetWindowPosition; 102 device->SetWindowSize = VITA_SetWindowSize; 103 device->ShowWindow = VITA_ShowWindow; 104 device->HideWindow = VITA_HideWindow; 105 device->RaiseWindow = VITA_RaiseWindow; 106 device->MaximizeWindow = VITA_MaximizeWindow; 107 device->MinimizeWindow = VITA_MinimizeWindow; 108 device->RestoreWindow = VITA_RestoreWindow; 109 device->SetWindowMouseGrab = VITA_SetWindowGrab; 110 device->SetWindowKeyboardGrab = VITA_SetWindowGrab; 111 device->DestroyWindow = VITA_DestroyWindow; 112 113 /* 114 // Disabled, causes issues on high-framerate updates. SDL still emulates this. 115 device->CreateWindowFramebuffer = VITA_CreateWindowFramebuffer; 116 device->UpdateWindowFramebuffer = VITA_UpdateWindowFramebuffer; 117 device->DestroyWindowFramebuffer = VITA_DestroyWindowFramebuffer; 118 */ 119 120#if defined(SDL_VIDEO_VITA_PIB) || defined(SDL_VIDEO_VITA_PVR) 121#ifdef SDL_VIDEO_VITA_PVR_OGL 122 if (SDL_GetHintBoolean(SDL_HINT_VITA_PVR_OPENGL, false)) { 123 device->GL_LoadLibrary = VITA_GL_LoadLibrary; 124 device->GL_CreateContext = VITA_GL_CreateContext; 125 device->GL_GetProcAddress = VITA_GL_GetProcAddress; 126 } else { 127#endif 128 device->GL_LoadLibrary = VITA_GLES_LoadLibrary; 129 device->GL_CreateContext = VITA_GLES_CreateContext; 130 device->GL_GetProcAddress = VITA_GLES_GetProcAddress; 131#ifdef SDL_VIDEO_VITA_PVR_OGL 132 } 133#endif 134 135 device->GL_UnloadLibrary = VITA_GLES_UnloadLibrary; 136 device->GL_MakeCurrent = VITA_GLES_MakeCurrent; 137 device->GL_SetSwapInterval = VITA_GLES_SetSwapInterval; 138 device->GL_GetSwapInterval = VITA_GLES_GetSwapInterval; 139 device->GL_SwapWindow = VITA_GLES_SwapWindow; 140 device->GL_DestroyContext = VITA_GLES_DestroyContext; 141#endif 142 143 device->HasScreenKeyboardSupport = VITA_HasScreenKeyboardSupport; 144 device->ShowScreenKeyboard = VITA_ShowScreenKeyboard; 145 device->HideScreenKeyboard = VITA_HideScreenKeyboard; 146 147 device->PumpEvents = VITA_PumpEvents; 148 149 device->device_caps = VIDEO_DEVICE_CAPS_FULLSCREEN_ONLY; 150 151 return device; 152} 153 154VideoBootStrap VITA_bootstrap = { 155 "vita", 156 "VITA Video Driver", 157 VITA_Create, 158 VITA_ShowMessageBox, 159 false 160}; 161 162/*****************************************************************************/ 163// SDL Video and Display initialization/handling functions 164/*****************************************************************************/ 165bool VITA_VideoInit(SDL_VideoDevice *_this) 166{ 167 SDL_DisplayMode mode; 168#ifdef SDL_VIDEO_VITA_PVR 169 const char *res = SDL_GetHint(SDL_HINT_VITA_RESOLUTION); 170#endif 171 SDL_zero(mode); 172 173#ifdef SDL_VIDEO_VITA_PVR 174 if (res) { 175 // 1088i for PSTV (Or Sharpscale) 176 if (SDL_strncmp(res, "1080", 4) == 0) { 177 mode.w = 1920; 178 mode.h = 1088; 179 } 180 // 725p for PSTV (Or Sharpscale) 181 else if (SDL_strncmp(res, "720", 3) == 0) { 182 mode.w = 1280; 183 mode.h = 725; 184 } 185 } 186 // 544p 187 else { 188#endif 189 mode.w = 960; 190 mode.h = 544; 191#ifdef SDL_VIDEO_VITA_PVR 192 } 193#endif 194 195 mode.refresh_rate = 60.0f; 196 197 // 32 bpp for default 198 mode.format = SDL_PIXELFORMAT_ABGR8888; 199 200 if (SDL_AddBasicVideoDisplay(&mode) == 0) { 201 return false; 202 } 203 204 VITA_InitTouch(); 205 VITA_InitKeyboard(); 206 VITA_InitMouse(); 207 208 return true; 209} 210 211void VITA_VideoQuit(SDL_VideoDevice *_this) 212{ 213 VITA_QuitTouch(); 214} 215 216bool VITA_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) 217{ 218 SDL_WindowData *wdata; 219#ifdef SDL_VIDEO_VITA_PVR 220 Psp2NativeWindow win; 221 int temp_major = 2; 222 int temp_minor = 1; 223 int temp_profile = 0; 224#endif 225 226 // Allocate window internal data 227 wdata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); 228 if (!wdata) { 229 return false; 230 } 231 232 // Setup driver data for this window 233 window->internal = wdata; 234 235 // Vita can only have one window 236 if (Vita_Window) { 237 return SDL_SetError("Only one window supported"); 238 } 239 240 Vita_Window = window; 241 242#ifdef SDL_VIDEO_VITA_PVR 243 win.type = PSP2_DRAWABLE_TYPE_WINDOW; 244 win.numFlipBuffers = 2; 245 win.flipChainThrdAffinity = 0x20000; 246 247 // 1088i for PSTV (Or Sharpscale) 248 if (window->w == 1920) { 249 win.windowSize = PSP2_WINDOW_1920X1088; 250 } 251 // 725p for PSTV (Or Sharpscale) 252 else if (window->w == 1280) { 253 win.windowSize = PSP2_WINDOW_1280X725; 254 } 255 // 544p 256 else { 257 win.windowSize = PSP2_WINDOW_960X544; 258 } 259 if (window->flags & SDL_WINDOW_OPENGL) { 260 bool use_opengl = SDL_GetHintBoolean(SDL_HINT_VITA_PVR_OPENGL, false); 261 if (use_opengl) { 262 // Set version to 2.1 and PROFILE to ES 263 temp_major = _this->gl_config.major_version; 264 temp_minor = _this->gl_config.minor_version; 265 temp_profile = _this->gl_config.profile_mask; 266 267 _this->gl_config.major_version = 2; 268 _this->gl_config.minor_version = 1; 269 _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES; 270 } 271 wdata->egl_surface = SDL_EGL_CreateSurface(_this, window, &win); 272 if (wdata->egl_surface == EGL_NO_SURFACE) { 273 return SDL_SetError("Could not create GLES window surface"); 274 } 275 if (use_opengl) { 276 // Revert 277 _this->gl_config.major_version = temp_major; 278 _this->gl_config.minor_version = temp_minor; 279 _this->gl_config.profile_mask = temp_profile; 280 } 281 } 282#endif 283 284 // fix input, we need to find a better way 285 SDL_SetKeyboardFocus(window); 286 287 // Window has been successfully created 288 return true; 289} 290 291void VITA_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) 292{ 293} 294bool VITA_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window) 295{ 296 return SDL_Unsupported(); 297} 298void VITA_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) 299{ 300} 301void VITA_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) 302{ 303} 304void VITA_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) 305{ 306} 307void VITA_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window) 308{ 309} 310void VITA_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window) 311{ 312} 313void VITA_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) 314{ 315} 316void VITA_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) 317{ 318} 319bool VITA_SetWindowGrab(SDL_VideoDevice *_this, SDL_Window *window, bool grabbed) 320{ 321 return true; 322} 323 324void VITA_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) 325{ 326 SDL_WindowData *data; 327 328 data = window->internal; 329 SDL_free(data); 330 331 window->internal = NULL; 332 Vita_Window = NULL; 333} 334 335bool VITA_HasScreenKeyboardSupport(SDL_VideoDevice *_this) 336{ 337 return true; 338} 339 340#ifndef SCE_IME_LANGUAGE_ENGLISH_US 341#define SCE_IME_LANGUAGE_ENGLISH_US SCE_IME_LANGUAGE_ENGLISH 342#endif 343 344static void utf16_to_utf8(const uint16_t *src, uint8_t *dst) 345{ 346 int i; 347 for (i = 0; src[i]; i++) { 348 if (!(src[i] & 0xFF80)) { 349 *(dst++) = src[i] & 0xFF; 350 } else if (!(src[i] & 0xF800)) { 351 *(dst++) = ((src[i] >> 6) & 0xFF) | 0xC0; 352 *(dst++) = (src[i] & 0x3F) | 0x80; 353 } else if ((src[i] & 0xFC00) == 0xD800 && (src[i + 1] & 0xFC00) == 0xDC00) { 354 *(dst++) = (((src[i] + 64) >> 8) & 0x3) | 0xF0; 355 *(dst++) = (((src[i] >> 2) + 16) & 0x3F) | 0x80; 356 *(dst++) = ((src[i] >> 4) & 0x30) | 0x80 | ((src[i + 1] << 2) & 0xF); 357 *(dst++) = (src[i + 1] & 0x3F) | 0x80; 358 i += 1; 359 } else { 360 *(dst++) = ((src[i] >> 12) & 0xF) | 0xE0; 361 *(dst++) = ((src[i] >> 6) & 0x3F) | 0x80; 362 *(dst++) = (src[i] & 0x3F) | 0x80; 363 } 364 } 365 366 *dst = '\0'; 367} 368 369#ifdef SDL_VIDEO_VITA_PVR 370SceWChar16 libime_out[SCE_IME_MAX_PREEDIT_LENGTH + SCE_IME_MAX_TEXT_LENGTH + 1]; 371char libime_initval[8] = { 1 }; 372SceImeCaret caret_rev; 373 374void VITA_ImeEventHandler(void *arg, const SceImeEventData *e) 375{ 376 SDL_VideoData *videodata = (SDL_VideoData *)arg; 377 uint8_t utf8_buffer[SCE_IME_MAX_TEXT_LENGTH]; 378 switch (e->id) { 379 case SCE_IME_EVENT_UPDATE_TEXT: 380 if (e->param.text.caretIndex == 0) { 381 SDL_SendKeyboardKeyAutoRelease(0, SDL_SCANCODE_BACKSPACE); 382 sceImeSetText((SceWChar16 *)libime_initval, 4); 383 } else { 384 utf16_to_utf8((SceWChar16 *)&libime_out[1], utf8_buffer); 385 if (utf8_buffer[0] == ' ') { 386 SDL_SendKeyboardKeyAutoRelease(0, SDL_SCANCODE_SPACE); 387 } else { 388 SDL_SendKeyboardText((const char *)utf8_buffer); 389 } 390 SDL_memset(&caret_rev, 0, sizeof(SceImeCaret)); 391 SDL_memset(libime_out, 0, ((SCE_IME_MAX_PREEDIT_LENGTH + SCE_IME_MAX_TEXT_LENGTH + 1) * sizeof(SceWChar16))); 392 caret_rev.index = 1; 393 sceImeSetCaret(&caret_rev); 394 sceImeSetText((SceWChar16 *)libime_initval, 4); 395 } 396 break; 397 case SCE_IME_EVENT_PRESS_ENTER: 398 SDL_SendKeyboardKeyAutoRelease(0, SDL_SCANCODE_RETURN); 399 break; 400 case SCE_IME_EVENT_PRESS_CLOSE: 401 sceImeClose(); 402 videodata->ime_active = false; 403 SDL_SendScreenKeyboardHidden(); 404 break; 405 } 406} 407#endif // SDL_VIDEO_VITA_PVR 408 409void VITA_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) 410{ 411 SDL_VideoData *videodata = _this->internal; 412 SceInt32 res; 413 414#ifdef SDL_VIDEO_VITA_PVR 415 416 SceUInt32 libime_work[SCE_IME_WORK_BUFFER_SIZE / sizeof(SceInt32)]; 417 SceImeParam param; 418 419 sceImeParamInit(&param); 420 421 SDL_memset(libime_out, 0, ((SCE_IME_MAX_PREEDIT_LENGTH + SCE_IME_MAX_TEXT_LENGTH + 1) * sizeof(SceWChar16))); 422 423 param.supportedLanguages = SCE_IME_LANGUAGE_ENGLISH_US; 424 param.languagesForced = SCE_FALSE; 425 switch (SDL_GetTextInputType(props)) { 426 default: 427 case SDL_TEXTINPUT_TYPE_TEXT: 428 param.type = SCE_IME_TYPE_DEFAULT; 429 break; 430 case SDL_TEXTINPUT_TYPE_TEXT_NAME: 431 param.type = SCE_IME_TYPE_DEFAULT; 432 break; 433 case SDL_TEXTINPUT_TYPE_TEXT_EMAIL: 434 param.type = SCE_IME_TYPE_MAIL; 435 break; 436 case SDL_TEXTINPUT_TYPE_TEXT_USERNAME: 437 param.type = SCE_IME_TYPE_DEFAULT; 438 break; 439 case SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_HIDDEN: 440 param.type = SCE_IME_TYPE_DEFAULT; 441 break; 442 case SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_VISIBLE: 443 param.type = SCE_IME_TYPE_DEFAULT; 444 break; 445 case SDL_TEXTINPUT_TYPE_NUMBER: 446 param.type = SCE_IME_TYPE_NUMBER; 447 break; 448 case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_HIDDEN: 449 param.type = SCE_IME_TYPE_NUMBER; 450 break; 451 case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_VISIBLE: 452 param.type = SCE_IME_TYPE_NUMBER; 453 break; 454 } 455 param.option = 0; 456 if (SDL_GetTextInputCapitalization(props) != SDL_CAPITALIZE_SENTENCES) { 457 param.option |= SCE_IME_OPTION_NO_AUTO_CAPITALIZATION; 458 } 459 if (!SDL_GetTextInputAutocorrect(props)) { 460 param.option |= SCE_IME_OPTION_NO_ASSISTANCE; 461 } 462 if (SDL_GetTextInputMultiline(props)) { 463 param.option |= SCE_IME_OPTION_MULTILINE; 464 } 465 param.inputTextBuffer = libime_out; 466 param.maxTextLength = SCE_IME_MAX_TEXT_LENGTH; 467 param.handler = VITA_ImeEventHandler; 468 param.filter = NULL; 469 param.initialText = (SceWChar16 *)libime_initval; 470 param.arg = videodata; 471 param.work = libime_work; 472 473 res = sceImeOpen(&param); 474 if (res < 0) { 475 SDL_SetError("Failed to init IME"); 476 return; 477 } 478 479#else 480 SceWChar16 *title = u""; 481 SceWChar16 *text = u""; 482 483 SceImeDialogParam param; 484 sceImeDialogParamInit(&param); 485 486 param.supportedLanguages = 0; 487 param.languagesForced = SCE_FALSE; 488 param.type = SCE_IME_TYPE_DEFAULT; 489 param.option = 0; 490 param.textBoxMode = SCE_IME_DIALOG_TEXTBOX_MODE_WITH_CLEAR; 491 param.maxTextLength = SCE_IME_DIALOG_MAX_TEXT_LENGTH; 492 493 param.title = title; 494 param.initialText = text; 495 param.inputTextBuffer = videodata->ime_buffer; 496 497 res = sceImeDialogInit(&param); 498 if (res < 0) { 499 SDL_SetError("Failed to init IME dialog"); 500 return; 501 } 502 503#endif 504 505 videodata->ime_active = true; 506 507 SDL_SendScreenKeyboardShown(); 508} 509 510void VITA_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window) 511{ 512#ifndef SDL_VIDEO_VITA_PVR 513 SDL_VideoData *videodata = _this->internal; 514 515 SceCommonDialogStatus dialogStatus = sceImeDialogGetStatus(); 516 517 switch (dialogStatus) { 518 default: 519 case SCE_COMMON_DIALOG_STATUS_NONE: 520 case SCE_COMMON_DIALOG_STATUS_RUNNING: 521 break; 522 case SCE_COMMON_DIALOG_STATUS_FINISHED: 523 sceImeDialogTerm(); 524 break; 525 } 526 527 videodata->ime_active = false; 528 529 SDL_SendScreenKeyboardHidden(); 530#endif 531} 532 533void VITA_PumpEvents(SDL_VideoDevice *_this) 534{ 535#ifndef SDL_VIDEO_VITA_PVR 536 SDL_VideoData *videodata = _this->internal; 537#endif 538 539 if (_this->suspend_screensaver) { 540 // cancel all idle timers to prevent vita going to sleep 541 sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DEFAULT); 542 } 543 544 VITA_PollTouch(); 545 VITA_PollKeyboard(); 546 VITA_PollMouse(); 547 548#ifndef SDL_VIDEO_VITA_PVR 549 if (videodata->ime_active == true) { 550 // update IME status. Terminate, if finished 551 SceCommonDialogStatus dialogStatus = sceImeDialogGetStatus(); 552 if (dialogStatus == SCE_COMMON_DIALOG_STATUS_FINISHED) { 553 uint8_t utf8_buffer[SCE_IME_DIALOG_MAX_TEXT_LENGTH]; 554 555 SceImeDialogResult result; 556 SDL_memset(&result, 0, sizeof(SceImeDialogResult)); 557 sceImeDialogGetResult(&result); 558 559 // Convert UTF16 to UTF8 560 utf16_to_utf8(videodata->ime_buffer, utf8_buffer); 561 562 // Send SDL event 563 SDL_SendKeyboardText((const char *)utf8_buffer); 564 565 // Send enter key only on enter 566 if (result.button == SCE_IME_DIALOG_BUTTON_ENTER) { 567 SDL_SendKeyboardKeyAutoRelease(0, SDL_SCANCODE_RETURN); 568 } 569 570 sceImeDialogTerm(); 571 572 videodata->ime_active = false; 573 574 SDL_SendScreenKeyboardHidden(); 575 } 576 } 577#endif 578} 579 580#endif // SDL_VIDEO_DRIVER_VITA 581
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.