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
post_SkEvent_event()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
skia_setBitmapFromSurface(SkBitmap * dst,SDL_Surface * src)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
SkOSWindow(void * screen)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
~SkOSWindow()64 SkOSWindow::~SkOSWindow() {
65 delete fGLCanvas;
66 if (fSurface) {
67 SDL_FreeSurface(fSurface);
68 }
69 }
70
71 #include <OpenGL/gl.h>
72
doDraw()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
find_skkey(SDLKey src)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
handleSDLEvent(const SDL_Event & event)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
onHandleInval(const SkIRect & r)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
onSetTitle(const char title[])201 void SkOSWindow::onSetTitle(const char title[]) {
202 SDL_WM_SetCaption(title, NULL);
203 }
204
onAddMenu(const SkOSMenu * sk_menu)205 void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu) {}
206
207 ///////////////////////////////////////////////////////////////////////////////////////
208
SignalNonEmptyQueue()209 void SkEvent::SignalNonEmptyQueue() {
210 SkDebugf("-------- signal nonempty\n");
211 post_SkEvent_event();
212 }
213
timer_callback(Uint32 interval)214 static Uint32 timer_callback(Uint32 interval) {
215 // SkDebugf("-------- timercallback %d\n", interval);
216 SkEvent::ServiceQueueTimer();
217 return 0;
218 }
219
SignalQueueTimer(SkMSec delay)220 void SkEvent::SignalQueueTimer(SkMSec delay)
221 {
222 SDL_SetTimer(0, NULL);
223 if (delay) {
224 SDL_SetTimer(delay, timer_callback);
225 }
226 }
227