| OLD | NEW |
| 1 | |
| 2 /* | 1 /* |
| 3 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 4 * | 3 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 7 */ | 6 */ |
| 8 #include "SkOSWindow_SDL.h" | 7 #include "SkOSWindow_SDL.h" |
| 9 #include "SkCanvas.h" | 8 #include "SkCanvas.h" |
| 10 #include "SkColorPriv.h" | 9 |
| 11 #include "SkGLCanvas.h" | 10 #include <GL/gl.h> |
| 12 #include "SkOSMenu.h" | 11 |
| 13 #include "SkTime.h" | 12 const int SCREEN_WIDTH = 640; |
| 14 | 13 const int SCREEN_HEIGHT = 480; |
| 15 static void post_SkEvent_event() { | 14 |
| 16 SDL_Event evt; | 15 static void handle_error() { |
| 17 evt.type = SDL_USEREVENT; | 16 const char* error = SDL_GetError(); |
| 18 evt.user.type = SDL_USEREVENT; | 17 SkDebugf("SDL Error: %s\n", error); |
| 19 evt.user.code = 0; | 18 SDL_ClearError(); |
| 20 evt.user.data1 = nullptr; | 19 } |
| 21 evt.user.data2 = nullptr; | 20 |
| 22 SDL_PushEvent(&evt); | 21 SkOSWindow::SkOSWindow(void* screen) : fQuit(false) , fGLContext(nullptr) { |
| 23 } | 22 //Create window |
| 24 | 23 SDL_Init(SDL_INIT_VIDEO|SDL_INIT_GAMECONTROLLER|SDL_INIT_EVENTS); |
| 25 static bool skia_setBitmapFromSurface(SkBitmap* dst, SDL_Surface* src) { | 24 fWindow = SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOW
POS_UNDEFINED, |
| 26 SkColorType ct; | 25 SCREEN_WIDTH, SCREEN_HEIGHT, |
| 27 SkAlphaType at; | 26 SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN ); |
| 28 | 27 if (!fWindow) { |
| 29 switch (src->format->BytesPerPixel) { | 28 handle_error(); |
| 30 case 2: | 29 return; |
| 31 ct = kRGB_565_SkColorType; | 30 } |
| 32 at = kOpaque_SkAlphaType; | 31 SDL_StartTextInput(); |
| 33 break; | 32 this->resize(SCREEN_WIDTH, SCREEN_HEIGHT); |
| 34 case 4: | 33 } |
| 35 ct = kN32_SkColorType; | 34 |
| 36 at = kPremul_SkAlphaType; | 35 SkOSWindow::~SkOSWindow() { |
| 37 break; | 36 if (fGLContext) { |
| 37 SDL_GL_DeleteContext(fGLContext); |
| 38 } |
| 39 |
| 40 //Destroy window |
| 41 SDL_DestroyWindow(fWindow); |
| 42 |
| 43 //Quit SDL subsystems |
| 44 SDL_Quit(); |
| 45 } |
| 46 |
| 47 void SkOSWindow::detach() { |
| 48 if (fGLContext) { |
| 49 SDL_GL_DeleteContext(fGLContext); |
| 50 fGLContext = nullptr; |
| 51 } |
| 52 } |
| 53 |
| 54 bool SkOSWindow::attach(SkBackEndTypes attachType, int msaaSampleCount, Attachme
ntInfo*) { |
| 55 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); |
| 56 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); |
| 57 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE
); |
| 58 |
| 59 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); |
| 60 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); |
| 61 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); |
| 62 |
| 63 if (msaaSampleCount > 0) { |
| 64 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); |
| 65 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaaSampleCount); |
| 66 } |
| 67 |
| 68 fGLContext = SDL_GL_CreateContext(fWindow); |
| 69 if (!fGLContext) { |
| 70 handle_error(); |
| 71 return false; |
| 72 } |
| 73 |
| 74 int success = SDL_GL_MakeCurrent(fWindow, fGLContext); |
| 75 if (success != 0) { |
| 76 handle_error(); |
| 77 return false; |
| 78 } |
| 79 |
| 80 glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); |
| 81 glClearColor(1, 1, 1, 1); |
| 82 glClearStencil(0); |
| 83 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
| 84 |
| 85 return true; |
| 86 } |
| 87 |
| 88 void SkOSWindow::present() { |
| 89 SDL_GL_SwapWindow(fWindow); |
| 90 } |
| 91 |
| 92 bool SkOSWindow::makeFullscreen() { |
| 93 SDL_SetWindowFullscreen(fWindow, SDL_WINDOW_FULLSCREEN); |
| 94 return true; |
| 95 } |
| 96 |
| 97 void SkOSWindow::setVsync(bool vsync) { |
| 98 SDL_GL_SetSwapInterval(vsync ? 1 : 0); |
| 99 } |
| 100 |
| 101 void SkOSWindow::closeWindow() { |
| 102 fQuit = true; |
| 103 } |
| 104 |
| 105 static SkKey convert_sdlkey_to_skkey(SDL_Keycode src) { |
| 106 switch (src) { |
| 107 case SDLK_UP: |
| 108 return kUp_SkKey; |
| 109 case SDLK_DOWN: |
| 110 return kDown_SkKey; |
| 111 case SDLK_LEFT: |
| 112 return kLeft_SkKey; |
| 113 case SDLK_RIGHT: |
| 114 return kRight_SkKey; |
| 115 case SDLK_HOME: |
| 116 return kHome_SkKey; |
| 117 case SDLK_END: |
| 118 return kEnd_SkKey; |
| 119 case SDLK_ASTERISK: |
| 120 return kStar_SkKey; |
| 121 case SDLK_HASH: |
| 122 return kHash_SkKey; |
| 123 case SDLK_0: |
| 124 return k0_SkKey; |
| 125 case SDLK_1: |
| 126 return k1_SkKey; |
| 127 case SDLK_2: |
| 128 return k2_SkKey; |
| 129 case SDLK_3: |
| 130 return k3_SkKey; |
| 131 case SDLK_4: |
| 132 return k4_SkKey; |
| 133 case SDLK_5: |
| 134 return k5_SkKey; |
| 135 case SDLK_6: |
| 136 return k6_SkKey; |
| 137 case SDLK_7: |
| 138 return k7_SkKey; |
| 139 case SDLK_8: |
| 140 return k8_SkKey; |
| 141 case SDLK_9: |
| 142 return k9_SkKey; |
| 38 default: | 143 default: |
| 39 return false; | 144 return kNONE_SkKey; |
| 40 } | 145 } |
| 41 | 146 } |
| 42 return dst->installPixels(SkImageInfo::Make(src->w, src->h, ct, at), src->pi
xels, src->pitch); | 147 |
| 43 } | 148 void SkOSWindow::handleEvents() { |
| 44 | 149 SkEvent::ServiceQueueTimer(); |
| 45 SkOSWindow::SkOSWindow(void* screen) { | 150 SkEvent::ProcessEvent(); |
| 46 fScreen = reinterpret_cast<SDL_Surface*>(screen); | 151 |
| 47 this->resize(fScreen->w, fScreen->h); | 152 SDL_Event event; |
| 48 | 153 while(SDL_PollEvent(&event)) { |
| 49 uint32_t rmask = SK_R32_MASK << SK_R32_SHIFT; | 154 switch (event.type) { |
| 50 uint32_t gmask = SK_G32_MASK << SK_G32_SHIFT; | 155 case SDL_MOUSEMOTION: |
| 51 uint32_t bmask = SK_B32_MASK << SK_B32_SHIFT; | 156 if (event.motion.state == SDL_PRESSED) { |
| 52 uint32_t amask = SK_A32_MASK << SK_A32_SHIFT; | 157 this->handleClick(event.motion.x, event.motion.y, |
| 53 | 158 SkView::Click::kMoved_State, nullptr); |
| 54 if (fScreen->flags & SDL_OPENGL) { | 159 } |
| 55 fSurface = nullptr; | 160 break; |
| 56 fGLCanvas = new SkGLCanvas; | 161 case SDL_MOUSEBUTTONDOWN: |
| 57 fGLCanvas->setViewport(fScreen->w, fScreen->h); | 162 case SDL_MOUSEBUTTONUP: |
| 58 } else { | 163 this->handleClick(event.button.x, event.button.y, |
| 59 fGLCanvas = nullptr; | 164 event.button.state == SDL_PRESSED ? |
| 60 fSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, fScreen->w, fScreen->h, | 165 SkView::Click::kDown_State : |
| 61 32, rmask, gmask, bmask, amask); | 166 SkView::Click::kUp_State, nullptr); |
| 62 } | 167 break; |
| 63 } | 168 case SDL_KEYDOWN: { |
| 64 | 169 SDL_Keycode key = event.key.keysym.sym; |
| 65 SkOSWindow::~SkOSWindow() { | 170 SkKey sk = convert_sdlkey_to_skkey(key); |
| 66 delete fGLCanvas; | 171 if (kNONE_SkKey != sk) { |
| 67 if (fSurface) { | 172 if (event.key.state == SDL_PRESSED) { |
| 68 SDL_FreeSurface(fSurface); | 173 this->handleKey(sk); |
| 69 } | 174 } else { |
| 70 } | 175 this->handleKeyUp(sk); |
| 71 | 176 } |
| 72 #include <OpenGL/gl.h> | 177 } else if (key == SDLK_ESCAPE) { |
| 73 | 178 fQuit = true; |
| 74 void SkOSWindow::doDraw() { | 179 } |
| 75 if (fGLCanvas) { | 180 break; |
| 76 glEnable(GL_BLEND); | |
| 77 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
| 78 glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE); | |
| 79 glEnable(GL_TEXTURE_2D); | |
| 80 glClearColor(0, 0, 0, 0); | |
| 81 glClear(GL_COLOR_BUFFER_BIT); | |
| 82 | |
| 83 int count = fGLCanvas->save(); | |
| 84 this->draw(fGLCanvas); | |
| 85 fGLCanvas->restoreToCount(count); | |
| 86 SDL_GL_SwapBuffers( ); | |
| 87 } else { | |
| 88 if ( SDL_MUSTLOCK(fSurface) ) { | |
| 89 if ( SDL_LockSurface(fSurface) < 0 ) { | |
| 90 return; | |
| 91 } | 181 } |
| 182 case SDL_TEXTINPUT: { |
| 183 size_t len = strlen(event.text.text); |
| 184 for (size_t i = 0; i < len; i++) { |
| 185 this->handleChar((SkUnichar)event.text.text[i]); |
| 186 } |
| 187 break; |
| 188 } |
| 189 case SDL_QUIT: |
| 190 fQuit = true; |
| 191 break; |
| 192 default: |
| 193 break; |
| 92 } | 194 } |
| 93 | 195 } |
| 94 SkBitmap bitmap; | 196 } |
| 95 | 197 |
| 96 if (skia_setBitmapFromSurface(&bitmap, fSurface)) { | |
| 97 SkCanvas canvas(bitmap); | |
| 98 this->draw(&canvas); | |
| 99 } | |
| 100 | |
| 101 if ( SDL_MUSTLOCK(fSurface) ) { | |
| 102 SDL_UnlockSurface(fSurface); | |
| 103 } | |
| 104 | |
| 105 int result = SDL_BlitSurface(fSurface, nullptr, fScreen, nullptr); | |
| 106 if (result) { | |
| 107 SkDebugf("------- SDL_BlitSurface returned %d\n", result); | |
| 108 } | |
| 109 SDL_UpdateRect(fScreen, 0, 0, fScreen->w, fScreen->h); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 static SkKey find_skkey(SDLKey src) { | |
| 114 // this array must match the enum order in SkKey.h | |
| 115 static const SDLKey gKeys[] = { | |
| 116 SDLK_UNKNOWN, | |
| 117 SDLK_UNKNOWN, // left softkey | |
| 118 SDLK_UNKNOWN, // right softkey | |
| 119 SDLK_UNKNOWN, // home | |
| 120 SDLK_UNKNOWN, // back | |
| 121 SDLK_UNKNOWN, // send | |
| 122 SDLK_UNKNOWN, // end | |
| 123 SDLK_0, | |
| 124 SDLK_1, | |
| 125 SDLK_2, | |
| 126 SDLK_3, | |
| 127 SDLK_4, | |
| 128 SDLK_5, | |
| 129 SDLK_6, | |
| 130 SDLK_7, | |
| 131 SDLK_8, | |
| 132 SDLK_9, | |
| 133 SDLK_ASTERISK, | |
| 134 SDLK_HASH, | |
| 135 SDLK_UP, | |
| 136 SDLK_DOWN, | |
| 137 SDLK_LEFT, | |
| 138 SDLK_RIGHT, | |
| 139 SDLK_RETURN, // OK | |
| 140 SDLK_UNKNOWN, // volume up | |
| 141 SDLK_UNKNOWN, // volume down | |
| 142 SDLK_UNKNOWN, // power | |
| 143 SDLK_UNKNOWN, // camera | |
| 144 }; | |
| 145 | |
| 146 const SDLKey* array = gKeys; | |
| 147 for (size_t i = 0; i < SK_ARRAY_COUNT(gKeys); i++) { | |
| 148 if (array[i] == src) { | |
| 149 return static_cast<SkKey>(i); | |
| 150 } | |
| 151 } | |
| 152 return kNONE_SkKey; | |
| 153 } | |
| 154 | |
| 155 void SkOSWindow::handleSDLEvent(const SDL_Event& event) { | |
| 156 switch (event.type) { | |
| 157 case SDL_VIDEORESIZE: | |
| 158 this->resize(event.resize.w, event.resize.h); | |
| 159 break; | |
| 160 case SDL_VIDEOEXPOSE: | |
| 161 this->doDraw(); | |
| 162 break; | |
| 163 case SDL_MOUSEMOTION: | |
| 164 if (event.motion.state == SDL_PRESSED) { | |
| 165 this->handleClick(event.motion.x, event.motion.y, | |
| 166 SkView::Click::kMoved_State); | |
| 167 } | |
| 168 break; | |
| 169 case SDL_MOUSEBUTTONDOWN: | |
| 170 case SDL_MOUSEBUTTONUP: | |
| 171 this->handleClick(event.button.x, event.button.y, | |
| 172 event.button.state == SDL_PRESSED ? | |
| 173 SkView::Click::kDown_State : | |
| 174 SkView::Click::kUp_State); | |
| 175 break; | |
| 176 case SDL_KEYDOWN: { | |
| 177 SkKey sk = find_skkey(event.key.keysym.sym); | |
| 178 if (kNONE_SkKey != sk) { | |
| 179 if (event.key.state == SDL_PRESSED) { | |
| 180 this->handleKey(sk); | |
| 181 } else { | |
| 182 this->handleKeyUp(sk); | |
| 183 } | |
| 184 } | |
| 185 break; | |
| 186 } | |
| 187 case SDL_USEREVENT: | |
| 188 if (SkEvent::ProcessEvent()) { | |
| 189 post_SkEvent_event(); | |
| 190 } | |
| 191 break; | |
| 192 } | |
| 193 } | |
| 194 | |
| 195 void SkOSWindow::onHandleInval(const SkIRect& r) { | |
| 196 SDL_Event evt; | |
| 197 evt.type = SDL_VIDEOEXPOSE; | |
| 198 evt.expose.type = SDL_VIDEOEXPOSE; | |
| 199 SDL_PushEvent(&evt); | |
| 200 } | |
| 201 | 198 |
| 202 void SkOSWindow::onSetTitle(const char title[]) { | 199 void SkOSWindow::onSetTitle(const char title[]) { |
| 203 SDL_WM_SetCaption(title, nullptr); | 200 SDL_SetWindowTitle(fWindow, title); |
| 204 } | 201 } |
| 205 | |
| 206 void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu) {} | |
| 207 | |
| 208 ////////////////////////////////////////////////////////////////////////////////
/////// | 202 ////////////////////////////////////////////////////////////////////////////////
/////// |
| 209 | 203 |
| 210 void SkEvent::SignalNonEmptyQueue() { | 204 void SkEvent::SignalNonEmptyQueue() { |
| 211 SkDebugf("-------- signal nonempty\n"); | 205 // nothing to do, since we spin on our event-queue |
| 212 post_SkEvent_event(); | 206 } |
| 213 } | 207 |
| 214 | 208 void SkEvent::SignalQueueTimer(SkMSec delay) { |
| 215 static Uint32 timer_callback(Uint32 interval) { | 209 // just need to record the delay time. We handle waking up for it in |
| 216 // SkDebugf("-------- timercallback %d\n", interval); | 210 } |
| 217 SkEvent::ServiceQueueTimer(); | 211 |
| 212 ////////////////////////////////////////////////////////////////////////////////
////////////// |
| 213 |
| 214 |
| 215 #include "SkApplication.h" |
| 216 #include "SkEvent.h" |
| 217 #include "SkWindow.h" |
| 218 |
| 219 int main(int argc, char** argv){ |
| 220 SkOSWindow* window = create_sk_window(nullptr, argc, argv); |
| 221 |
| 222 // drain any events that occurred before |window| was assigned. |
| 223 while (SkEvent::ProcessEvent()); |
| 224 |
| 225 // Start normal Skia sequence |
| 226 application_init(); |
| 227 |
| 228 window->loop(); |
| 229 |
| 230 delete window; |
| 231 application_term(); |
| 218 return 0; | 232 return 0; |
| 219 } | 233 } |
| 220 | |
| 221 void SkEvent::SignalQueueTimer(SkMSec delay) | |
| 222 { | |
| 223 SDL_SetTimer(0, nullptr); | |
| 224 if (delay) { | |
| 225 SDL_SetTimer(delay, timer_callback); | |
| 226 } | |
| 227 } | |
| OLD | NEW |