video.c (9512B)
1 /* 2 Simple DirectMedia Layer 3 Copyright (C) 2017 BlackBerry Limited 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 #include "../../SDL_internal.h" 22 #include "../SDL_sysvideo.h" 23 #include "sdl_qnx.h" 24 25 static screen_context_t context; 26 static screen_event_t event; 27 28 /** 29 * Initializes the QNX video plugin. 30 * Creates the Screen context and event handles used for all window operations 31 * by the plugin. 32 * @param _THIS 33 * @return 0 if successful, -1 on error 34 */ 35 static int 36 videoInit(_THIS) 37 { 38 SDL_VideoDisplay display; 39 40 if (screen_create_context(&context, 0) < 0) { 41 return -1; 42 } 43 44 if (screen_create_event(&event) < 0) { 45 return -1; 46 } 47 48 SDL_zero(display); 49 50 if (SDL_AddVideoDisplay(&display, SDL_FALSE) < 0) { 51 return -1; 52 } 53 54 _this->num_displays = 1; 55 return 0; 56 } 57 58 static void 59 videoQuit(_THIS) 60 { 61 } 62 63 /** 64 * Creates a new native Screen window and associates it with the given SDL 65 * window. 66 * @param _THIS 67 * @param window SDL window to initialize 68 * @return 0 if successful, -1 on error 69 */ 70 static int 71 createWindow(_THIS, SDL_Window *window) 72 { 73 window_impl_t *impl; 74 int size[2]; 75 int numbufs; 76 int format; 77 int usage; 78 79 impl = SDL_calloc(1, sizeof(*impl)); 80 if (impl == NULL) { 81 return -1; 82 } 83 84 // Create a native window. 85 if (screen_create_window(&impl->window, context) < 0) { 86 goto fail; 87 } 88 89 // Set the native window's size to match the SDL window. 90 size[0] = window->w; 91 size[1] = window->h; 92 93 if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SIZE, 94 size) < 0) { 95 goto fail; 96 } 97 98 if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SOURCE_SIZE, 99 size) < 0) { 100 goto fail; 101 } 102 103 // Create window buffer(s). 104 if (window->flags & SDL_WINDOW_OPENGL) { 105 if (glGetConfig(&impl->conf, &format) < 0) { 106 goto fail; 107 } 108 numbufs = 2; 109 110 usage = SCREEN_USAGE_OPENGL_ES2; 111 if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_USAGE, 112 &usage) < 0) { 113 return -1; 114 } 115 } else { 116 format = SCREEN_FORMAT_RGBX8888; 117 numbufs = 1; 118 } 119 120 // Set pixel format. 121 if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_FORMAT, 122 &format) < 0) { 123 goto fail; 124 } 125 126 // Create buffer(s). 127 if (screen_create_window_buffers(impl->window, numbufs) < 0) { 128 goto fail; 129 } 130 131 window->driverdata = impl; 132 return 0; 133 134 fail: 135 if (impl->window) { 136 screen_destroy_window(impl->window); 137 } 138 139 SDL_free(impl); 140 return -1; 141 } 142 143 /** 144 * Gets a pointer to the Screen buffer associated with the given window. Note 145 * that the buffer is actually created in createWindow(). 146 * @param _THIS 147 * @param window SDL window to get the buffer for 148 * @param[out] pixles Holds a pointer to the window's buffer 149 * @param[out] format Holds the pixel format for the buffer 150 * @param[out] pitch Holds the number of bytes per line 151 * @return 0 if successful, -1 on error 152 */ 153 static int 154 createWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, 155 void ** pixels, int *pitch) 156 { 157 window_impl_t *impl = (window_impl_t *)window->driverdata; 158 screen_buffer_t buffer; 159 160 // Get a pointer to the buffer's memory. 161 if (screen_get_window_property_pv(impl->window, SCREEN_PROPERTY_BUFFERS, 162 (void **)&buffer) < 0) { 163 return -1; 164 } 165 166 if (screen_get_buffer_property_pv(buffer, SCREEN_PROPERTY_POINTER, 167 pixels) < 0) { 168 return -1; 169 } 170 171 // Set format and pitch. 172 if (screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_STRIDE, 173 pitch) < 0) { 174 return -1; 175 } 176 177 *format = SDL_PIXELFORMAT_RGB888; 178 return 0; 179 } 180 181 /** 182 * Informs the window manager that the window needs to be updated. 183 * @param _THIS 184 * @param window The window to update 185 * @param rects An array of reectangular areas to update 186 * @param numrects Rect array length 187 * @return 0 if successful, -1 on error 188 */ 189 static int 190 updateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects, 191 int numrects) 192 { 193 window_impl_t *impl = (window_impl_t *)window->driverdata; 194 screen_buffer_t buffer; 195 196 if (screen_get_window_property_pv(impl->window, SCREEN_PROPERTY_BUFFERS, 197 (void **)&buffer) < 0) { 198 return -1; 199 } 200 201 screen_post_window(impl->window, buffer, numrects, (int *)rects, 0); 202 screen_flush_context(context, 0); 203 return 0; 204 } 205 206 /** 207 * Runs the main event loop. 208 * @param _THIS 209 */ 210 static void 211 pumpEvents(_THIS) 212 { 213 int type; 214 215 for (;;) { 216 if (screen_get_event(context, event, 0) < 0) { 217 break; 218 } 219 220 if (screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type) 221 < 0) { 222 break; 223 } 224 225 if (type == SCREEN_EVENT_NONE) { 226 break; 227 } 228 229 switch (type) { 230 case SCREEN_EVENT_KEYBOARD: 231 handleKeyboardEvent(event); 232 break; 233 234 default: 235 break; 236 } 237 } 238 } 239 240 /** 241 * Updates the size of the native window using the geometry of the SDL window. 242 * @param _THIS 243 * @param window SDL window to update 244 */ 245 static void 246 setWindowSize(_THIS, SDL_Window *window) 247 { 248 window_impl_t *impl = (window_impl_t *)window->driverdata; 249 int size[2]; 250 251 size[0] = window->w; 252 size[1] = window->h; 253 254 screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SIZE, size); 255 screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SOURCE_SIZE, 256 size); 257 } 258 259 /** 260 * Makes the native window associated with the given SDL window visible. 261 * @param _THIS 262 * @param window SDL window to update 263 */ 264 static void 265 showWindow(_THIS, SDL_Window *window) 266 { 267 window_impl_t *impl = (window_impl_t *)window->driverdata; 268 const int visible = 1; 269 270 screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_VISIBLE, 271 &visible); 272 } 273 274 /** 275 * Makes the native window associated with the given SDL window invisible. 276 * @param _THIS 277 * @param window SDL window to update 278 */ 279 static void 280 hideWindow(_THIS, SDL_Window *window) 281 { 282 window_impl_t *impl = (window_impl_t *)window->driverdata; 283 const int visible = 0; 284 285 screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_VISIBLE, 286 &visible); 287 } 288 289 /** 290 * Destroys the native window associated with the given SDL window. 291 * @param _THIS 292 * @param window SDL window that is being destroyed 293 */ 294 static void 295 destroyWindow(_THIS, SDL_Window *window) 296 { 297 window_impl_t *impl = (window_impl_t *)window->driverdata; 298 299 if (impl) { 300 screen_destroy_window(impl->window); 301 window->driverdata = NULL; 302 } 303 } 304 305 /** 306 * Frees the plugin object created by createDevice(). 307 * @param device Plugin object to free 308 */ 309 static void 310 deleteDevice(SDL_VideoDevice *device) 311 { 312 SDL_free(device); 313 } 314 315 /** 316 * Creates the QNX video plugin used by SDL. 317 * @param devindex Unused 318 * @return Initialized device if successful, NULL otherwise 319 */ 320 static SDL_VideoDevice * 321 createDevice(int devindex) 322 { 323 SDL_VideoDevice *device; 324 325 device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); 326 if (device == NULL) { 327 return NULL; 328 } 329 330 device->driverdata = NULL; 331 device->VideoInit = videoInit; 332 device->VideoQuit = videoQuit; 333 device->CreateSDLWindow = createWindow; 334 device->CreateWindowFramebuffer = createWindowFramebuffer; 335 device->UpdateWindowFramebuffer = updateWindowFramebuffer; 336 device->SetWindowSize = setWindowSize; 337 device->ShowWindow = showWindow; 338 device->HideWindow = hideWindow; 339 device->PumpEvents = pumpEvents; 340 device->DestroyWindow = destroyWindow; 341 342 device->GL_LoadLibrary = glLoadLibrary; 343 device->GL_GetProcAddress = glGetProcAddress; 344 device->GL_CreateContext = glCreateContext; 345 device->GL_SetSwapInterval = glSetSwapInterval; 346 device->GL_SwapWindow = glSwapWindow; 347 device->GL_MakeCurrent = glMakeCurrent; 348 device->GL_DeleteContext = glDeleteContext; 349 device->GL_UnloadLibrary = glUnloadLibrary; 350 351 device->free = deleteDevice; 352 return device; 353 } 354 355 VideoBootStrap QNX_bootstrap = { 356 "qnx", "QNX Screen", 357 createDevice 358 };