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    SkColorType ct;
27    SkAlphaType at;
28
29    switch (src->format->BytesPerPixel) {
30        case 2:
31            ct = kRGB_565_SkColorType;
32            at = kOpaque_SkAlphaType;
33            break;
34        case 4:
35            ct = kN32_SkColorType;
36            at = kPremul_SkAlphaType;
37            break;
38        default:
39            return false;
40    }
41
42    return dst->installPixels(SkImageInfo::Make(src->w, src->h, ct, at), src->pixels, src->pitch);
43}
44
45SkOSWindow::SkOSWindow(void* screen) {
46    fScreen = reinterpret_cast<SDL_Surface*>(screen);
47    this->resize(fScreen->w, fScreen->h);
48
49    uint32_t rmask = SK_R32_MASK << SK_R32_SHIFT;
50    uint32_t gmask = SK_G32_MASK << SK_G32_SHIFT;
51    uint32_t bmask = SK_B32_MASK << SK_B32_SHIFT;
52    uint32_t amask = SK_A32_MASK << SK_A32_SHIFT;
53
54    if (fScreen->flags & SDL_OPENGL) {
55        fSurface = NULL;
56        fGLCanvas = new SkGLCanvas;
57        fGLCanvas->setViewport(fScreen->w, fScreen->h);
58    } else {
59        fGLCanvas = NULL;
60        fSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, fScreen->w, fScreen->h,
61                                        32, rmask, gmask, bmask, amask);
62    }
63}
64
65SkOSWindow::~SkOSWindow() {
66    delete fGLCanvas;
67    if (fSurface) {
68        SDL_FreeSurface(fSurface);
69    }
70}
71
72#include <OpenGL/gl.h>
73
74void SkOSWindow::doDraw() {
75    if (fGLCanvas) {
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            }
92        }
93
94        SkBitmap bitmap;
95
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, NULL, fScreen, NULL);
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
113static 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
155void 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
195void 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
202void SkOSWindow::onSetTitle(const char title[]) {
203    SDL_WM_SetCaption(title, NULL);
204}
205
206void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu) {}
207
208///////////////////////////////////////////////////////////////////////////////////////
209
210void SkEvent::SignalNonEmptyQueue() {
211    SkDebugf("-------- signal nonempty\n");
212    post_SkEvent_event();
213}
214
215static Uint32 timer_callback(Uint32 interval) {
216//    SkDebugf("-------- timercallback %d\n", interval);
217    SkEvent::ServiceQueueTimer();
218    return 0;
219}
220
221void SkEvent::SignalQueueTimer(SkMSec delay)
222{
223    SDL_SetTimer(0, NULL);
224    if (delay) {
225        SDL_SetTimer(delay, timer_callback);
226    }
227}
228