00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "pandabase.h"
00016
00017 #ifdef HAVE_SDL
00018
00019 #include "tinySDLGraphicsWindow.h"
00020 #include "tinyGraphicsStateGuardian.h"
00021 #include "config_tinydisplay.h"
00022 #include "tinySDLGraphicsPipe.h"
00023 #include "mouseButton.h"
00024 #include "keyboardButton.h"
00025 #include "graphicsPipe.h"
00026
00027 TypeHandle TinySDLGraphicsWindow::_type_handle;
00028
00029
00030
00031
00032
00033
00034 TinySDLGraphicsWindow::
00035 TinySDLGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
00036 const string &name,
00037 const FrameBufferProperties &fb_prop,
00038 const WindowProperties &win_prop,
00039 int flags,
00040 GraphicsStateGuardian *gsg,
00041 GraphicsOutput *host) :
00042 GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
00043 {
00044 _screen = NULL;
00045 _frame_buffer = NULL;
00046 _pitch = 0;
00047 update_pixel_factor();
00048
00049 GraphicsWindowInputDevice device =
00050 GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
00051 add_input_device(device);
00052 }
00053
00054
00055
00056
00057
00058
00059 TinySDLGraphicsWindow::
00060 ~TinySDLGraphicsWindow() {
00061 }
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 bool TinySDLGraphicsWindow::
00073 begin_frame(FrameMode mode, Thread *current_thread) {
00074 begin_frame_spam(mode);
00075 if (_gsg == (GraphicsStateGuardian *)NULL) {
00076 return false;
00077 }
00078
00079 TinyGraphicsStateGuardian *tinygsg;
00080 DCAST_INTO_R(tinygsg, _gsg, false);
00081
00082 tinygsg->_current_frame_buffer = _frame_buffer;
00083 tinygsg->reset_if_new();
00084
00085 _gsg->set_current_properties(&get_fb_properties());
00086 return _gsg->begin_frame(current_thread);
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096 void TinySDLGraphicsWindow::
00097 end_frame(FrameMode mode, Thread *current_thread) {
00098 end_frame_spam(mode);
00099 nassertv(_gsg != (GraphicsStateGuardian *)NULL);
00100
00101 if (mode == FM_render) {
00102
00103 copy_to_textures();
00104 }
00105
00106 _gsg->end_frame(current_thread);
00107
00108 if (mode == FM_render) {
00109 trigger_flip();
00110 }
00111 }
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 void TinySDLGraphicsWindow::
00124 end_flip() {
00125 if (!_flip_ready) {
00126 GraphicsWindow::end_flip();
00127 return;
00128 }
00129
00130 int fb_xsize = get_fb_x_size();
00131 int fb_ysize = get_fb_y_size();
00132
00133 if (fb_xsize == _frame_buffer->xsize) {
00134
00135 if (SDL_MUSTLOCK(_screen)) {
00136 if (SDL_LockSurface(_screen) < 0) {
00137 tinydisplay_cat.error()
00138 << "Can't lock screen: " << SDL_GetError() << "\n";
00139 }
00140 }
00141 ZB_copyFrameBuffer(_frame_buffer, _screen->pixels, _pitch);
00142
00143 if (SDL_MUSTLOCK(_screen)) {
00144 SDL_UnlockSurface(_screen);
00145 }
00146
00147 } else {
00148
00149 SDL_Surface *temp =
00150 SDL_CreateRGBSurfaceFrom(_frame_buffer->pbuf, _frame_buffer->xsize, _frame_buffer->ysize,
00151 32, _frame_buffer->linesize, 0xff0000, 0x00ff00, 0x0000ff, 0xff000000);
00152 SDL_SetAlpha(temp, SDL_RLEACCEL, 0);
00153 SDL_BlitSurface(temp, NULL, _screen, NULL);
00154 SDL_FreeSurface(temp);
00155 }
00156
00157 SDL_Flip(_screen);
00158 GraphicsWindow::end_flip();
00159 }
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 void TinySDLGraphicsWindow::
00172 process_events() {
00173 GraphicsWindow::process_events();
00174
00175 if (_screen == NULL) {
00176 return;
00177 }
00178
00179 WindowProperties properties;
00180
00181 SDL_Event evt;
00182 ButtonHandle button;
00183 while (SDL_PollEvent(&evt)) {
00184 switch(evt.type) {
00185 case SDL_KEYDOWN:
00186 if (evt.key.keysym.unicode) {
00187 _input_devices[0].keystroke(evt.key.keysym.unicode);
00188 }
00189 button = get_keyboard_button(evt.key.keysym.sym);
00190 if (button != ButtonHandle::none()) {
00191 _input_devices[0].button_down(button);
00192 }
00193 break;
00194
00195 case SDL_KEYUP:
00196 button = get_keyboard_button(evt.key.keysym.sym);
00197 if (button != ButtonHandle::none()) {
00198 _input_devices[0].button_up(button);
00199 }
00200 break;
00201
00202 case SDL_MOUSEBUTTONDOWN:
00203 button = get_mouse_button(evt.button.button);
00204 _input_devices[0].set_pointer_in_window(evt.button.x, evt.button.y);
00205 _input_devices[0].button_down(button);
00206 break;
00207
00208 case SDL_MOUSEBUTTONUP:
00209 button = get_mouse_button(evt.button.button);
00210 _input_devices[0].set_pointer_in_window(evt.button.x, evt.button.y);
00211 _input_devices[0].button_up(button);
00212 break;
00213
00214 case SDL_MOUSEMOTION:
00215 _input_devices[0].set_pointer_in_window(evt.motion.x, evt.motion.y);
00216 break;
00217
00218 case SDL_VIDEORESIZE:
00219 properties.set_size(evt.resize.w, evt.resize.h);
00220 system_changed_properties(properties);
00221 _screen = SDL_SetVideoMode(_properties.get_x_size(), _properties.get_y_size(), 32, _flags);
00222 ZB_resize(_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size());
00223 _pitch = _screen->pitch * 32 / _screen->format->BitsPerPixel;
00224 break;
00225
00226 case SDL_QUIT:
00227
00228 close_window();
00229 properties.set_open(false);
00230 system_changed_properties(properties);
00231 break;
00232 }
00233 }
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 void TinySDLGraphicsWindow::
00254 set_properties_now(WindowProperties &properties) {
00255 GraphicsWindow::set_properties_now(properties);
00256 if (!properties.is_any_specified()) {
00257
00258 return;
00259 }
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 bool TinySDLGraphicsWindow::
00277 supports_pixel_zoom() const {
00278 return true;
00279 }
00280
00281
00282
00283
00284
00285
00286
00287 void TinySDLGraphicsWindow::
00288 close_window() {
00289 GraphicsWindow::close_window();
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299 bool TinySDLGraphicsWindow::
00300 open_window() {
00301
00302
00303 TinyGraphicsStateGuardian *tinygsg;
00304 if (_gsg == 0) {
00305
00306 tinygsg = new TinyGraphicsStateGuardian(_engine, _pipe, NULL);
00307 _gsg = tinygsg;
00308
00309 } else {
00310 DCAST_INTO_R(tinygsg, _gsg, false);
00311 }
00312
00313 _flags = SDL_SWSURFACE;
00314 if (_properties.get_fullscreen()) {
00315 _flags |= SDL_FULLSCREEN;
00316 }
00317 if (!_properties.get_fixed_size()) {
00318 _flags |= SDL_RESIZABLE;
00319 }
00320 if (_properties.get_undecorated()) {
00321 _flags |= SDL_NOFRAME;
00322 }
00323 _screen = SDL_SetVideoMode(_properties.get_x_size(), _properties.get_y_size(), 32, _flags);
00324
00325 if (_screen == NULL) {
00326 tinydisplay_cat.error()
00327 << "Video mode set failed.\n";
00328 return false;
00329 }
00330
00331 create_frame_buffer();
00332 if (_frame_buffer == NULL) {
00333 tinydisplay_cat.error()
00334 << "Could not create frame buffer.\n";
00335 return false;
00336 }
00337
00338 tinygsg->_current_frame_buffer = _frame_buffer;
00339
00340
00341
00342
00343
00344 tinygsg->reset_if_new();
00345
00346 return true;
00347 }
00348
00349
00350
00351
00352
00353
00354
00355 void TinySDLGraphicsWindow::
00356 create_frame_buffer() {
00357 if (_frame_buffer != NULL) {
00358 ZB_close(_frame_buffer);
00359 _frame_buffer = NULL;
00360 }
00361
00362 int mode;
00363 switch (_screen->format->BitsPerPixel) {
00364 case 8:
00365 tinydisplay_cat.error()
00366 << "SDL Palettes are currently not supported.\n";
00367 return;
00368
00369 case 16:
00370 mode = ZB_MODE_5R6G5B;
00371 break;
00372 case 24:
00373 mode = ZB_MODE_RGB24;
00374 break;
00375 case 32:
00376 mode = ZB_MODE_RGBA;
00377 break;
00378
00379 default:
00380 return;
00381 }
00382
00383 _frame_buffer = ZB_open(_properties.get_x_size(), _properties.get_y_size(), mode, 0, 0, 0, 0);
00384
00385 _pitch = _screen->pitch * 32 / _screen->format->BitsPerPixel;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394 ButtonHandle TinySDLGraphicsWindow::
00395 get_keyboard_button(SDLKey sym) {
00396 switch (sym) {
00397 case SDLK_BACKSPACE: return KeyboardButton::backspace();
00398 case SDLK_TAB: return KeyboardButton::tab();
00399
00400 case SDLK_RETURN: return KeyboardButton::enter();
00401
00402 case SDLK_ESCAPE: return KeyboardButton::escape();
00403 case SDLK_SPACE: return KeyboardButton::space();
00404 case SDLK_EXCLAIM: return KeyboardButton::ascii_key('!');
00405 case SDLK_QUOTEDBL: return KeyboardButton::ascii_key('"');
00406 case SDLK_HASH: return KeyboardButton::ascii_key('#');
00407 case SDLK_DOLLAR: return KeyboardButton::ascii_key('$');
00408 case SDLK_AMPERSAND: return KeyboardButton::ascii_key('&');
00409 case SDLK_QUOTE: return KeyboardButton::ascii_key('\'');
00410 case SDLK_LEFTPAREN: return KeyboardButton::ascii_key('(');
00411 case SDLK_RIGHTPAREN: return KeyboardButton::ascii_key(')');
00412 case SDLK_ASTERISK: return KeyboardButton::ascii_key('*');
00413 case SDLK_PLUS: return KeyboardButton::ascii_key('+');
00414 case SDLK_COMMA: return KeyboardButton::ascii_key(',');
00415 case SDLK_MINUS: return KeyboardButton::ascii_key('-');
00416 case SDLK_PERIOD: return KeyboardButton::ascii_key('.');
00417 case SDLK_SLASH: return KeyboardButton::ascii_key('/');
00418 case SDLK_0: return KeyboardButton::ascii_key('0');
00419 case SDLK_1: return KeyboardButton::ascii_key('1');
00420 case SDLK_2: return KeyboardButton::ascii_key('2');
00421 case SDLK_3: return KeyboardButton::ascii_key('3');
00422 case SDLK_4: return KeyboardButton::ascii_key('4');
00423 case SDLK_5: return KeyboardButton::ascii_key('5');
00424 case SDLK_6: return KeyboardButton::ascii_key('6');
00425 case SDLK_7: return KeyboardButton::ascii_key('7');
00426 case SDLK_8: return KeyboardButton::ascii_key('8');
00427 case SDLK_9: return KeyboardButton::ascii_key('9');
00428 case SDLK_COLON: return KeyboardButton::ascii_key(':');
00429 case SDLK_SEMICOLON: return KeyboardButton::ascii_key(';');
00430 case SDLK_LESS: return KeyboardButton::ascii_key('<');
00431 case SDLK_EQUALS: return KeyboardButton::ascii_key('=');
00432 case SDLK_GREATER: return KeyboardButton::ascii_key('>');
00433 case SDLK_QUESTION: return KeyboardButton::ascii_key('?');
00434 case SDLK_AT: return KeyboardButton::ascii_key('@');
00435 case SDLK_LEFTBRACKET: return KeyboardButton::ascii_key('[');
00436 case SDLK_BACKSLASH: return KeyboardButton::ascii_key('\\');
00437 case SDLK_RIGHTBRACKET: return KeyboardButton::ascii_key(']');
00438 case SDLK_CARET: return KeyboardButton::ascii_key('^');
00439 case SDLK_UNDERSCORE: return KeyboardButton::ascii_key('_');
00440 case SDLK_BACKQUOTE: return KeyboardButton::ascii_key('`');
00441 case SDLK_a: return KeyboardButton::ascii_key('a');
00442 case SDLK_b: return KeyboardButton::ascii_key('b');
00443 case SDLK_c: return KeyboardButton::ascii_key('c');
00444 case SDLK_d: return KeyboardButton::ascii_key('d');
00445 case SDLK_e: return KeyboardButton::ascii_key('e');
00446 case SDLK_f: return KeyboardButton::ascii_key('f');
00447 case SDLK_g: return KeyboardButton::ascii_key('g');
00448 case SDLK_h: return KeyboardButton::ascii_key('h');
00449 case SDLK_i: return KeyboardButton::ascii_key('i');
00450 case SDLK_j: return KeyboardButton::ascii_key('j');
00451 case SDLK_k: return KeyboardButton::ascii_key('k');
00452 case SDLK_l: return KeyboardButton::ascii_key('l');
00453 case SDLK_m: return KeyboardButton::ascii_key('m');
00454 case SDLK_n: return KeyboardButton::ascii_key('n');
00455 case SDLK_o: return KeyboardButton::ascii_key('o');
00456 case SDLK_p: return KeyboardButton::ascii_key('p');
00457 case SDLK_q: return KeyboardButton::ascii_key('q');
00458 case SDLK_r: return KeyboardButton::ascii_key('r');
00459 case SDLK_s: return KeyboardButton::ascii_key('s');
00460 case SDLK_t: return KeyboardButton::ascii_key('t');
00461 case SDLK_u: return KeyboardButton::ascii_key('u');
00462 case SDLK_v: return KeyboardButton::ascii_key('v');
00463 case SDLK_w: return KeyboardButton::ascii_key('w');
00464 case SDLK_x: return KeyboardButton::ascii_key('x');
00465 case SDLK_y: return KeyboardButton::ascii_key('y');
00466 case SDLK_z: return KeyboardButton::ascii_key('z');
00467 case SDLK_DELETE: return KeyboardButton::del();
00468 case SDLK_KP0: return KeyboardButton::ascii_key('0');
00469 case SDLK_KP1: return KeyboardButton::ascii_key('1');
00470 case SDLK_KP2: return KeyboardButton::ascii_key('2');
00471 case SDLK_KP3: return KeyboardButton::ascii_key('3');
00472 case SDLK_KP4: return KeyboardButton::ascii_key('4');
00473 case SDLK_KP5: return KeyboardButton::ascii_key('5');
00474 case SDLK_KP6: return KeyboardButton::ascii_key('6');
00475 case SDLK_KP7: return KeyboardButton::ascii_key('7');
00476 case SDLK_KP8: return KeyboardButton::ascii_key('8');
00477 case SDLK_KP9: return KeyboardButton::ascii_key('9');
00478 case SDLK_KP_PERIOD: return KeyboardButton::ascii_key('.');
00479 case SDLK_KP_DIVIDE: return KeyboardButton::ascii_key('/');
00480 case SDLK_KP_MULTIPLY: return KeyboardButton::ascii_key('*');
00481 case SDLK_KP_MINUS: return KeyboardButton::ascii_key('-');
00482 case SDLK_KP_PLUS: return KeyboardButton::ascii_key('+');
00483 case SDLK_KP_ENTER: return KeyboardButton::enter();
00484 case SDLK_KP_EQUALS: return KeyboardButton::ascii_key('=');
00485 case SDLK_UP: return KeyboardButton::up();
00486 case SDLK_DOWN: return KeyboardButton::down();
00487 case SDLK_RIGHT: return KeyboardButton::right();
00488 case SDLK_LEFT: return KeyboardButton::left();
00489 case SDLK_INSERT: return KeyboardButton::insert();
00490 case SDLK_HOME: return KeyboardButton::home();
00491 case SDLK_END: return KeyboardButton::end();
00492 case SDLK_PAGEUP: return KeyboardButton::page_up();
00493 case SDLK_PAGEDOWN: return KeyboardButton::page_down();
00494 case SDLK_F1: return KeyboardButton::f1();
00495 case SDLK_F2: return KeyboardButton::f2();
00496 case SDLK_F3: return KeyboardButton::f3();
00497 case SDLK_F4: return KeyboardButton::f4();
00498 case SDLK_F5: return KeyboardButton::f5();
00499 case SDLK_F6: return KeyboardButton::f6();
00500 case SDLK_F7: return KeyboardButton::f7();
00501 case SDLK_F8: return KeyboardButton::f8();
00502 case SDLK_F9: return KeyboardButton::f9();
00503 case SDLK_F10: return KeyboardButton::f10();
00504 case SDLK_F11: return KeyboardButton::f11();
00505 case SDLK_F12: return KeyboardButton::f12();
00506 case SDLK_F13: return KeyboardButton::f13();
00507 case SDLK_F14: return KeyboardButton::f14();
00508 case SDLK_F15: return KeyboardButton::f15();
00509
00510
00511
00512 case SDLK_RSHIFT: return KeyboardButton::rshift();
00513 case SDLK_LSHIFT: return KeyboardButton::lshift();
00514 case SDLK_RCTRL: return KeyboardButton::rcontrol();
00515 case SDLK_LCTRL: return KeyboardButton::lcontrol();
00516 case SDLK_RALT: return KeyboardButton::ralt();
00517 case SDLK_LALT: return KeyboardButton::lalt();
00518 case SDLK_RMETA: return KeyboardButton::ralt();
00519 case SDLK_LMETA: return KeyboardButton::lalt();
00520
00521
00522
00523 case SDLK_HELP: return KeyboardButton::help();
00524
00525
00526
00527
00528
00529
00530 }
00531 tinydisplay_cat.info()
00532 << "unhandled keyboard button " << sym << "\n";
00533
00534 return ButtonHandle::none();
00535 }
00536
00537
00538
00539
00540
00541
00542
00543 ButtonHandle TinySDLGraphicsWindow::
00544 get_mouse_button(Uint8 button) {
00545 switch (button) {
00546 case SDL_BUTTON_LEFT:
00547 return MouseButton::one();
00548
00549 case SDL_BUTTON_MIDDLE:
00550 return MouseButton::two();
00551
00552 case SDL_BUTTON_RIGHT:
00553 return MouseButton::three();
00554
00555 case SDL_BUTTON_WHEELUP:
00556 return MouseButton::wheel_up();
00557
00558 case SDL_BUTTON_WHEELDOWN:
00559 return MouseButton::wheel_down();
00560 }
00561 tinydisplay_cat.info()
00562 << "unhandled mouse button " << button << "\n";
00563
00564 return ButtonHandle::none();
00565 }
00566
00567 #endif // HAVE_SDL