1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 #include "SkOSWindow_SDL.h" 9 #include "SkCanvas.h" 10 #include "SkColorPriv.h" 11 #include "SkGLCanvas.h" 12 #include "SkOSMenu.h" 13 #include "SkTime.h" 14 15 static void post_SkEvent_event() { 16 SDL_Event evt; 17 evt.type = SDL_USEREVENT; 18 evt.user.type = SDL_USEREVENT; 19 evt.user.code = 0; 20 evt.user.data1 = NULL; 21 evt.user.data2 = NULL; 22 SDL_PushEvent(&evt); 23 } 24 25 static bool skia_setBitmapFromSurface(SkBitmap* dst, SDL_Surface* src) { 26 SkBitmap::Config config; 27 28 switch (src->format->BytesPerPixel) { 29 case 2: 30 config = SkBitmap::kRGB_565_Config; 31 break; 32 case 4: 33 config = SkBitmap::kARGB_8888_Config; 34 break; 35 default: 36 return false; 37 } 38 39 dst->setConfig(config, src->w, src->h, src->pitch); 40 dst->setPixels(src->pixels); 41 return true; 42 } 43 44 SkOSWindow::SkOSWindow(void* screen) { 45 fScreen = reinterpret_cast<SDL_Surface*>(screen); 46 this->resize(fScreen->w, fScreen->h); 47 48 uint32_t rmask = SK_R32_MASK << SK_R32_SHIFT; 49 uint32_t gmask = SK_G32_MASK << SK_G32_SHIFT; 50 uint32_t bmask = SK_B32_MASK << SK_B32_SHIFT; 51 uint32_t amask = SK_A32_MASK << SK_A32_SHIFT; 52 53 if (fScreen->flags & SDL_OPENGL) { 54 fSurface = NULL; 55 fGLCanvas = new SkGLCanvas; 56 fGLCanvas->setViewport(fScreen->w, fScreen->h); 57 } else { 58 fGLCanvas = NULL; 59 fSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, fScreen->w, fScreen->h, 60 32, rmask, gmask, bmask, amask); 61 } 62 } 63 64 SkOSWindow::~SkOSWindow() { 65 delete fGLCanvas; 66 if (fSurface) { 67 SDL_FreeSurface(fSurface); 68 } 69 } 70 71 #include <OpenGL/gl.h> 72 73 void SkOSWindow::doDraw() { 74 if (fGLCanvas) { 75 glEnable(GL_BLEND); 76 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 77 glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE); 78 glEnable(GL_TEXTURE_2D); 79 glClearColor(0, 0, 0, 0); 80 glClear(GL_COLOR_BUFFER_BIT); 81 82 int count = fGLCanvas->save(); 83 this->draw(fGLCanvas); 84 fGLCanvas->restoreToCount(count); 85 SDL_GL_SwapBuffers( ); 86 } else { 87 if ( SDL_MUSTLOCK(fSurface) ) { 88 if ( SDL_LockSurface(fSurface) < 0 ) { 89 return; 90 } 91 } 92 93 SkBitmap bitmap; 94 95 if (skia_setBitmapFromSurface(&bitmap, fSurface)) { 96 SkCanvas canvas(bitmap); 97 this->draw(&canvas); 98 } 99 100 if ( SDL_MUSTLOCK(fSurface) ) { 101 SDL_UnlockSurface(fSurface); 102 } 103 104 int result = SDL_BlitSurface(fSurface, NULL, fScreen, NULL); 105 if (result) { 106 SkDebugf("------- SDL_BlitSurface returned %d\n", result); 107 } 108 SDL_UpdateRect(fScreen, 0, 0, fScreen->w, fScreen->h); 109 } 110 } 111 112 static SkKey find_skkey(SDLKey src) { 113 // this array must match the enum order in SkKey.h 114 static const SDLKey gKeys[] = { 115 SDLK_UNKNOWN, 116 SDLK_UNKNOWN, // left softkey 117 SDLK_UNKNOWN, // right softkey 118 SDLK_UNKNOWN, // home 119 SDLK_UNKNOWN, // back 120 SDLK_UNKNOWN, // send 121 SDLK_UNKNOWN, // end 122 SDLK_0, 123 SDLK_1, 124 SDLK_2, 125 SDLK_3, 126 SDLK_4, 127 SDLK_5, 128 SDLK_6, 129 SDLK_7, 130 SDLK_8, 131 SDLK_9, 132 SDLK_ASTERISK, 133 SDLK_HASH, 134 SDLK_UP, 135 SDLK_DOWN, 136 SDLK_LEFT, 137 SDLK_RIGHT, 138 SDLK_RETURN, // OK 139 SDLK_UNKNOWN, // volume up 140 SDLK_UNKNOWN, // volume down 141 SDLK_UNKNOWN, // power 142 SDLK_UNKNOWN, // camera 143 }; 144 145 const SDLKey* array = gKeys; 146 for (size_t i = 0; i < SK_ARRAY_COUNT(gKeys); i++) { 147 if (array[i] == src) { 148 return static_cast<SkKey>(i); 149 } 150 } 151 return kNONE_SkKey; 152 } 153 154 void SkOSWindow::handleSDLEvent(const SDL_Event& event) { 155 switch (event.type) { 156 case SDL_VIDEORESIZE: 157 this->resize(event.resize.w, event.resize.h); 158 break; 159 case SDL_VIDEOEXPOSE: 160 this->doDraw(); 161 break; 162 case SDL_MOUSEMOTION: 163 if (event.motion.state == SDL_PRESSED) { 164 this->handleClick(event.motion.x, event.motion.y, 165 SkView::Click::kMoved_State); 166 } 167 break; 168 case SDL_MOUSEBUTTONDOWN: 169 case SDL_MOUSEBUTTONUP: 170 this->handleClick(event.button.x, event.button.y, 171 event.button.state == SDL_PRESSED ? 172 SkView::Click::kDown_State : 173 SkView::Click::kUp_State); 174 break; 175 case SDL_KEYDOWN: { 176 SkKey sk = find_skkey(event.key.keysym.sym); 177 if (kNONE_SkKey != sk) { 178 if (event.key.state == SDL_PRESSED) { 179 this->handleKey(sk); 180 } else { 181 this->handleKeyUp(sk); 182 } 183 } 184 break; 185 } 186 case SDL_USEREVENT: 187 if (SkEvent::ProcessEvent()) { 188 post_SkEvent_event(); 189 } 190 break; 191 } 192 } 193 194 void SkOSWindow::onHandleInval(const SkIRect& r) { 195 SDL_Event evt; 196 evt.type = SDL_VIDEOEXPOSE; 197 evt.expose.type = SDL_VIDEOEXPOSE; 198 SDL_PushEvent(&evt); 199 } 200 201 void SkOSWindow::onSetTitle(const char title[]) { 202 SDL_WM_SetCaption(title, NULL); 203 } 204 205 void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu) {} 206 207 /////////////////////////////////////////////////////////////////////////////////////// 208 209 void SkEvent::SignalNonEmptyQueue() { 210 SkDebugf("-------- signal nonempty\n"); 211 post_SkEvent_event(); 212 } 213 214 static Uint32 timer_callback(Uint32 interval) { 215 // SkDebugf("-------- timercallback %d\n", interval); 216 SkEvent::ServiceQueueTimer(); 217 return 0; 218 } 219 220 void SkEvent::SignalQueueTimer(SkMSec delay) 221 { 222 SDL_SetTimer(0, NULL); 223 if (delay) { 224 SDL_SetTimer(delay, timer_callback); 225 } 226 } 227