Atlas - SDL_vitavideo.c

Home / ext / SDL / src / video / vita Lines: 1 | Size: 17220 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2026 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 // TODO: Is VIDEO_DEVICE_CAPS_SLOW_FRAMEBUFFER needed? 116 device->CreateWindowFramebuffer = VITA_CreateWindowFramebuffer; 117 device->UpdateWindowFramebuffer = VITA_UpdateWindowFramebuffer; 118 device->DestroyWindowFramebuffer = VITA_DestroyWindowFramebuffer; 119 */ 120 121#if defined(SDL_VIDEO_VITA_PIB) || defined(SDL_VIDEO_VITA_PVR) 122#ifdef SDL_VIDEO_VITA_PVR_OGL 123 if (SDL_GetHintBoolean(SDL_HINT_VITA_PVR_OPENGL, false)) { 124 device->GL_LoadLibrary = VITA_GL_LoadLibrary; 125 device->GL_CreateContext = VITA_GL_CreateContext; 126 device->GL_GetProcAddress = VITA_GL_GetProcAddress; 127 } else { 128#endif 129 device->GL_LoadLibrary = VITA_GLES_LoadLibrary; 130 device->GL_CreateContext = VITA_GLES_CreateContext; 131 device->GL_GetProcAddress = VITA_GLES_GetProcAddress; 132#ifdef SDL_VIDEO_VITA_PVR_OGL 133 } 134#endif 135 136 device->GL_UnloadLibrary = VITA_GLES_UnloadLibrary; 137 device->GL_MakeCurrent = VITA_GLES_MakeCurrent; 138 device->GL_SetSwapInterval = VITA_GLES_SetSwapInterval; 139 device->GL_GetSwapInterval = VITA_GLES_GetSwapInterval; 140 device->GL_SwapWindow = VITA_GLES_SwapWindow; 141 device->GL_DestroyContext = VITA_GLES_DestroyContext; 142#endif 143 144 device->HasScreenKeyboardSupport = VITA_HasScreenKeyboardSupport; 145 device->ShowScreenKeyboard = VITA_ShowScreenKeyboard; 146 device->HideScreenKeyboard = VITA_HideScreenKeyboard; 147 148 device->PumpEvents = VITA_PumpEvents; 149 150 device->device_caps = VIDEO_DEVICE_CAPS_FULLSCREEN_ONLY; 151 152 return device; 153} 154 155VideoBootStrap VITA_bootstrap = { 156 "vita", 157 "VITA Video Driver", 158 VITA_Create, 159 VITA_ShowMessageBox, 160 false 161}; 162 163/*****************************************************************************/ 164// SDL Video and Display initialization/handling functions 165/*****************************************************************************/ 166bool VITA_VideoInit(SDL_VideoDevice *_this) 167{ 168 SDL_DisplayMode mode; 169#ifdef SDL_VIDEO_VITA_PVR 170 const char *res = SDL_GetHint(SDL_HINT_VITA_RESOLUTION); 171#endif 172 SDL_zero(mode); 173 174#ifdef SDL_VIDEO_VITA_PVR 175 if (res) { 176 // 1088i for PSTV (Or Sharpscale) 177 if (SDL_strncmp(res, "1080", 4) == 0) { 178 mode.w = 1920; 179 mode.h = 1088; 180 } 181 // 725p for PSTV (Or Sharpscale) 182 else if (SDL_strncmp(res, "720", 3) == 0) { 183 mode.w = 1280; 184 mode.h = 725; 185 } 186 } 187 // 544p 188 else { 189#endif 190 mode.w = 960; 191 mode.h = 544; 192#ifdef SDL_VIDEO_VITA_PVR 193 } 194#endif 195 196 mode.refresh_rate = 60.0f; 197 198 // 32 bpp for default 199 mode.format = SDL_PIXELFORMAT_ABGR8888; 200 201 if (SDL_AddBasicVideoDisplay(&mode) == 0) { 202 return false; 203 } 204 205 VITA_InitTouch(); 206 VITA_InitKeyboard(); 207 VITA_InitMouse(); 208 209 return true; 210} 211 212void VITA_VideoQuit(SDL_VideoDevice *_this) 213{ 214 VITA_QuitTouch(); 215} 216 217bool VITA_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) 218{ 219 SDL_WindowData *wdata; 220#ifdef SDL_VIDEO_VITA_PVR 221 Psp2NativeWindow win; 222 int temp_major = 2; 223 int temp_minor = 1; 224 int temp_profile = 0; 225#endif 226 227 // Allocate window internal data 228 wdata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); 229 if (!wdata) { 230 return false; 231 } 232 233 // Setup driver data for this window 234 window->internal = wdata; 235 236 // Vita can only have one window 237 if (Vita_Window) { 238 return SDL_SetError("Only one window supported"); 239 } 240 241 Vita_Window = window; 242 243#ifdef SDL_VIDEO_VITA_PVR 244 win.type = PSP2_DRAWABLE_TYPE_WINDOW; 245 win.numFlipBuffers = 2; 246 win.flipChainThrdAffinity = 0x20000; 247 248 // 1088i for PSTV (Or Sharpscale) 249 if (window->w == 1920) { 250 win.windowSize = PSP2_WINDOW_1920X1088; 251 } 252 // 725p for PSTV (Or Sharpscale) 253 else if (window->w == 1280) { 254 win.windowSize = PSP2_WINDOW_1280X725; 255 } 256 // 544p 257 else { 258 win.windowSize = PSP2_WINDOW_960X544; 259 } 260 if (window->flags & SDL_WINDOW_OPENGL) { 261 bool use_opengl = SDL_GetHintBoolean(SDL_HINT_VITA_PVR_OPENGL, false); 262 if (use_opengl) { 263 // Set version to 2.1 and PROFILE to ES 264 temp_major = _this->gl_config.major_version; 265 temp_minor = _this->gl_config.minor_version; 266 temp_profile = _this->gl_config.profile_mask; 267 268 _this->gl_config.major_version = 2; 269 _this->gl_config.minor_version = 1; 270 _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES; 271 } 272 wdata->egl_surface = SDL_EGL_CreateSurface(_this, window, &win); 273 if (wdata->egl_surface == EGL_NO_SURFACE) { 274 return SDL_SetError("Could not create GLES window surface"); 275 } 276 if (use_opengl) { 277 // Revert 278 _this->gl_config.major_version = temp_major; 279 _this->gl_config.minor_version = temp_minor; 280 _this->gl_config.profile_mask = temp_profile; 281 } 282 } 283#endif 284 285 // fix input, we need to find a better way 286 SDL_SetKeyboardFocus(window); 287 288 // Window has been successfully created 289 return true; 290} 291 292void VITA_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) 293{ 294} 295bool VITA_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window) 296{ 297 return SDL_Unsupported(); 298} 299void VITA_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) 300{ 301} 302void VITA_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) 303{ 304} 305void VITA_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) 306{ 307} 308void VITA_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window) 309{ 310} 311void VITA_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window) 312{ 313} 314void VITA_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) 315{ 316} 317void VITA_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) 318{ 319} 320bool VITA_SetWindowGrab(SDL_VideoDevice *_this, SDL_Window *window, bool grabbed) 321{ 322 return true; 323} 324 325void VITA_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) 326{ 327 SDL_WindowData *data; 328 329 data = window->internal; 330 SDL_free(data); 331 332 window->internal = NULL; 333 Vita_Window = NULL; 334} 335 336bool VITA_HasScreenKeyboardSupport(SDL_VideoDevice *_this) 337{ 338 return true; 339} 340 341#ifndef SCE_IME_LANGUAGE_ENGLISH_US 342#define SCE_IME_LANGUAGE_ENGLISH_US SCE_IME_LANGUAGE_ENGLISH 343#endif 344 345static void utf16_to_utf8(const uint16_t *src, uint8_t *dst) 346{ 347 int i; 348 for (i = 0; src[i]; i++) { 349 if (!(src[i] & 0xFF80)) { 350 *(dst++) = src[i] & 0xFF; 351 } else if (!(src[i] & 0xF800)) { 352 *(dst++) = ((src[i] >> 6) & 0xFF) | 0xC0; 353 *(dst++) = (src[i] & 0x3F) | 0x80; 354 } else if ((src[i] & 0xFC00) == 0xD800 && (src[i + 1] & 0xFC00) == 0xDC00) { 355 *(dst++) = (((src[i] + 64) >> 8) & 0x3) | 0xF0; 356 *(dst++) = (((src[i] >> 2) + 16) & 0x3F) | 0x80; 357 *(dst++) = ((src[i] >> 4) & 0x30) | 0x80 | ((src[i + 1] << 2) & 0xF); 358 *(dst++) = (src[i + 1] & 0x3F) | 0x80; 359 i += 1; 360 } else { 361 *(dst++) = ((src[i] >> 12) & 0xF) | 0xE0; 362 *(dst++) = ((src[i] >> 6) & 0x3F) | 0x80; 363 *(dst++) = (src[i] & 0x3F) | 0x80; 364 } 365 } 366 367 *dst = '\0'; 368} 369 370#ifdef SDL_VIDEO_VITA_PVR 371SceWChar16 libime_out[SCE_IME_MAX_PREEDIT_LENGTH + SCE_IME_MAX_TEXT_LENGTH + 1]; 372char libime_initval[8] = { 1 }; 373SceImeCaret caret_rev; 374 375void VITA_ImeEventHandler(void *arg, const SceImeEventData *e) 376{ 377 SDL_VideoData *videodata = (SDL_VideoData *)arg; 378 uint8_t utf8_buffer[SCE_IME_MAX_TEXT_LENGTH]; 379 switch (e->id) { 380 case SCE_IME_EVENT_UPDATE_TEXT: 381 if (e->param.text.caretIndex == 0) { 382 SDL_SendKeyboardKeyAutoRelease(0, SDL_SCANCODE_BACKSPACE); 383 sceImeSetText((SceWChar16 *)libime_initval, 4); 384 } else { 385 utf16_to_utf8((SceWChar16 *)&libime_out[1], utf8_buffer); 386 if (utf8_buffer[0] == ' ') { 387 SDL_SendKeyboardKeyAutoRelease(0, SDL_SCANCODE_SPACE); 388 } else { 389 SDL_SendKeyboardText((const char *)utf8_buffer); 390 } 391 SDL_zero(caret_rev); 392 SDL_memset(libime_out, 0, ((SCE_IME_MAX_PREEDIT_LENGTH + SCE_IME_MAX_TEXT_LENGTH + 1) * sizeof(SceWChar16))); 393 caret_rev.index = 1; 394 sceImeSetCaret(&caret_rev); 395 sceImeSetText((SceWChar16 *)libime_initval, 4); 396 } 397 break; 398 case SCE_IME_EVENT_PRESS_ENTER: 399 SDL_SendKeyboardKeyAutoRelease(0, SDL_SCANCODE_RETURN); 400 break; 401 case SCE_IME_EVENT_PRESS_CLOSE: 402 sceImeClose(); 403 videodata->ime_active = false; 404 SDL_SendScreenKeyboardHidden(); 405 break; 406 } 407} 408#endif // SDL_VIDEO_VITA_PVR 409 410void VITA_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) 411{ 412 SDL_VideoData *videodata = _this->internal; 413 SceInt32 res; 414 415#ifdef SDL_VIDEO_VITA_PVR 416 417 SceUInt32 libime_work[SCE_IME_WORK_BUFFER_SIZE / sizeof(SceInt32)]; 418 SceImeParam param; 419 420 sceImeParamInit(&param); 421 422 SDL_memset(libime_out, 0, ((SCE_IME_MAX_PREEDIT_LENGTH + SCE_IME_MAX_TEXT_LENGTH + 1) * sizeof(SceWChar16))); 423 424 param.supportedLanguages = SCE_IME_LANGUAGE_ENGLISH_US; 425 param.languagesForced = SCE_FALSE; 426 switch (SDL_GetTextInputType(props)) { 427 default: 428 case SDL_TEXTINPUT_TYPE_TEXT: 429 param.type = SCE_IME_TYPE_DEFAULT; 430 break; 431 case SDL_TEXTINPUT_TYPE_TEXT_NAME: 432 param.type = SCE_IME_TYPE_DEFAULT; 433 break; 434 case SDL_TEXTINPUT_TYPE_TEXT_EMAIL: 435 param.type = SCE_IME_TYPE_MAIL; 436 break; 437 case SDL_TEXTINPUT_TYPE_TEXT_USERNAME: 438 param.type = SCE_IME_TYPE_DEFAULT; 439 break; 440 case SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_HIDDEN: 441 param.type = SCE_IME_TYPE_DEFAULT; 442 break; 443 case SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_VISIBLE: 444 param.type = SCE_IME_TYPE_DEFAULT; 445 break; 446 case SDL_TEXTINPUT_TYPE_NUMBER: 447 param.type = SCE_IME_TYPE_NUMBER; 448 break; 449 case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_HIDDEN: 450 param.type = SCE_IME_TYPE_NUMBER; 451 break; 452 case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_VISIBLE: 453 param.type = SCE_IME_TYPE_NUMBER; 454 break; 455 } 456 param.option = 0; 457 if (SDL_GetTextInputCapitalization(props) != SDL_CAPITALIZE_SENTENCES) { 458 param.option |= SCE_IME_OPTION_NO_AUTO_CAPITALIZATION; 459 } 460 if (!SDL_GetTextInputAutocorrect(props)) { 461 param.option |= SCE_IME_OPTION_NO_ASSISTANCE; 462 } 463 if (SDL_GetTextInputMultiline(props)) { 464 param.option |= SCE_IME_OPTION_MULTILINE; 465 } 466 param.inputTextBuffer = libime_out; 467 param.maxTextLength = SCE_IME_MAX_TEXT_LENGTH; 468 param.handler = VITA_ImeEventHandler; 469 param.filter = NULL; 470 param.initialText = (SceWChar16 *)libime_initval; 471 param.arg = videodata; 472 param.work = libime_work; 473 474 res = sceImeOpen(&param); 475 if (res < 0) { 476 SDL_SetError("Failed to init IME"); 477 return; 478 } 479 480#else 481 SceWChar16 *title = u""; 482 SceWChar16 *text = u""; 483 484 SceImeDialogParam param; 485 sceImeDialogParamInit(&param); 486 487 param.supportedLanguages = 0; 488 param.languagesForced = SCE_FALSE; 489 param.type = SCE_IME_TYPE_DEFAULT; 490 param.option = 0; 491 param.textBoxMode = SCE_IME_DIALOG_TEXTBOX_MODE_WITH_CLEAR; 492 param.maxTextLength = SCE_IME_DIALOG_MAX_TEXT_LENGTH; 493 494 param.title = title; 495 param.initialText = text; 496 param.inputTextBuffer = videodata->ime_buffer; 497 498 res = sceImeDialogInit(&param); 499 if (res < 0) { 500 SDL_SetError("Failed to init IME dialog"); 501 return; 502 } 503 504#endif 505 506 videodata->ime_active = true; 507 508 SDL_SendScreenKeyboardShown(); 509} 510 511void VITA_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window) 512{ 513#ifndef SDL_VIDEO_VITA_PVR 514 SDL_VideoData *videodata = _this->internal; 515 516 SceCommonDialogStatus dialogStatus = sceImeDialogGetStatus(); 517 518 switch (dialogStatus) { 519 default: 520 case SCE_COMMON_DIALOG_STATUS_NONE: 521 case SCE_COMMON_DIALOG_STATUS_RUNNING: 522 break; 523 case SCE_COMMON_DIALOG_STATUS_FINISHED: 524 sceImeDialogTerm(); 525 break; 526 } 527 528 videodata->ime_active = false; 529 530 SDL_SendScreenKeyboardHidden(); 531#endif 532} 533 534void VITA_PumpEvents(SDL_VideoDevice *_this) 535{ 536#ifndef SDL_VIDEO_VITA_PVR 537 SDL_VideoData *videodata = _this->internal; 538#endif 539 540 if (_this->suspend_screensaver) { 541 // cancel all idle timers to prevent vita going to sleep 542 sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DEFAULT); 543 } 544 545 VITA_PollTouch(); 546 VITA_PollKeyboard(); 547 VITA_PollMouse(); 548 549#ifndef SDL_VIDEO_VITA_PVR 550 if (videodata->ime_active == true) { 551 // update IME status. Terminate, if finished 552 SceCommonDialogStatus dialogStatus = sceImeDialogGetStatus(); 553 if (dialogStatus == SCE_COMMON_DIALOG_STATUS_FINISHED) { 554 uint8_t utf8_buffer[SCE_IME_DIALOG_MAX_TEXT_LENGTH]; 555 556 SceImeDialogResult result; 557 SDL_zero(result); 558 sceImeDialogGetResult(&result); 559 560 // Convert UTF16 to UTF8 561 utf16_to_utf8(videodata->ime_buffer, utf8_buffer); 562 563 // Send SDL event 564 SDL_SendKeyboardText((const char *)utf8_buffer); 565 566 // Send enter key only on enter 567 if (result.button == SCE_IME_DIALOG_BUTTON_ENTER) { 568 SDL_SendKeyboardKeyAutoRelease(0, SDL_SCANCODE_RETURN); 569 } 570 571 sceImeDialogTerm(); 572 573 videodata->ime_active = false; 574 575 SDL_SendScreenKeyboardHidden(); 576 } 577 } 578#endif 579} 580 581#endif // SDL_VIDEO_DRIVER_VITA 582
[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.