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 |