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