blob: 4edc5acfd30cbc221012d03c806d5cc3abbf5eed [file] [log] [blame]
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkOSWindow_SDL.h"
#include "SkCanvas.h"
#include "SkColorPriv.h"
#include "SkGLCanvas.h"
#include "SkOSMenu.h"
#include "SkTime.h"
static void post_SkEvent_event() {
SDL_Event evt;
evt.type = SDL_USEREVENT;
evt.user.type = SDL_USEREVENT;
evt.user.code = 0;
evt.user.data1 = NULL;
evt.user.data2 = NULL;
SDL_PushEvent(&evt);
}
static bool skia_setBitmapFromSurface(SkBitmap* dst, SDL_Surface* src) {
SkBitmap::Config config;
switch (src->format->BytesPerPixel) {
case 2:
config = SkBitmap::kRGB_565_Config;
break;
case 4:
config = SkBitmap::kARGB_8888_Config;
break;
default:
return false;
}
dst->setConfig(config, src->w, src->h, src->pitch);
dst->setPixels(src->pixels);
return true;
}
SkOSWindow::SkOSWindow(void* screen) {
fScreen = reinterpret_cast<SDL_Surface*>(screen);
this->resize(fScreen->w, fScreen->h);
uint32_t rmask = SK_R32_MASK << SK_R32_SHIFT;
uint32_t gmask = SK_G32_MASK << SK_G32_SHIFT;
uint32_t bmask = SK_B32_MASK << SK_B32_SHIFT;
uint32_t amask = SK_A32_MASK << SK_A32_SHIFT;
if (fScreen->flags & SDL_OPENGL) {
fSurface = NULL;
fGLCanvas = new SkGLCanvas;
fGLCanvas->setViewport(fScreen->w, fScreen->h);
} else {
fGLCanvas = NULL;
fSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, fScreen->w, fScreen->h,
32, rmask, gmask, bmask, amask);
}
}
SkOSWindow::~SkOSWindow() {
delete fGLCanvas;
if (fSurface) {
SDL_FreeSurface(fSurface);
}
}
#include <OpenGL/gl.h>
void SkOSWindow::doDraw() {
if (fGLCanvas) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
glEnable(GL_TEXTURE_2D);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
int count = fGLCanvas->save();
this->draw(fGLCanvas);
fGLCanvas->restoreToCount(count);
SDL_GL_SwapBuffers( );
} else {
if ( SDL_MUSTLOCK(fSurface) ) {
if ( SDL_LockSurface(fSurface) < 0 ) {
return;
}
}
SkBitmap bitmap;
if (skia_setBitmapFromSurface(&bitmap, fSurface)) {
SkCanvas canvas(bitmap);
this->draw(&canvas);
}
if ( SDL_MUSTLOCK(fSurface) ) {
SDL_UnlockSurface(fSurface);
}
int result = SDL_BlitSurface(fSurface, NULL, fScreen, NULL);
if (result) {
SkDebugf("------- SDL_BlitSurface returned %d\n", result);
}
SDL_UpdateRect(fScreen, 0, 0, fScreen->w, fScreen->h);
}
}
static SkKey find_skkey(SDLKey src) {
// this array must match the enum order in SkKey.h
static const SDLKey gKeys[] = {
SDLK_UNKNOWN,
SDLK_UNKNOWN, // left softkey
SDLK_UNKNOWN, // right softkey
SDLK_UNKNOWN, // home
SDLK_UNKNOWN, // back
SDLK_UNKNOWN, // send
SDLK_UNKNOWN, // end
SDLK_0,
SDLK_1,
SDLK_2,
SDLK_3,
SDLK_4,
SDLK_5,
SDLK_6,
SDLK_7,
SDLK_8,
SDLK_9,
SDLK_ASTERISK,
SDLK_HASH,
SDLK_UP,
SDLK_DOWN,
SDLK_LEFT,
SDLK_RIGHT,
SDLK_RETURN, // OK
SDLK_UNKNOWN, // volume up
SDLK_UNKNOWN, // volume down
SDLK_UNKNOWN, // power
SDLK_UNKNOWN, // camera
};
const SDLKey* array = gKeys;
for (size_t i = 0; i < SK_ARRAY_COUNT(gKeys); i++) {
if (array[i] == src) {
return static_cast<SkKey>(i);
}
}
return kNONE_SkKey;
}
void SkOSWindow::handleSDLEvent(const SDL_Event& event) {
switch (event.type) {
case SDL_VIDEORESIZE:
this->resize(event.resize.w, event.resize.h);
break;
case SDL_VIDEOEXPOSE:
this->doDraw();
break;
case SDL_MOUSEMOTION:
if (event.motion.state == SDL_PRESSED) {
this->handleClick(event.motion.x, event.motion.y,
SkView::Click::kMoved_State);
}
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
this->handleClick(event.button.x, event.button.y,
event.button.state == SDL_PRESSED ?
SkView::Click::kDown_State :
SkView::Click::kUp_State);
break;
case SDL_KEYDOWN: {
SkKey sk = find_skkey(event.key.keysym.sym);
if (kNONE_SkKey != sk) {
if (event.key.state == SDL_PRESSED) {
this->handleKey(sk);
} else {
this->handleKeyUp(sk);
}
}
break;
}
case SDL_USEREVENT:
if (SkEvent::ProcessEvent()) {
post_SkEvent_event();
}
break;
}
}
void SkOSWindow::onHandleInval(const SkIRect& r) {
SDL_Event evt;
evt.type = SDL_VIDEOEXPOSE;
evt.expose.type = SDL_VIDEOEXPOSE;
SDL_PushEvent(&evt);
}
void SkOSWindow::onSetTitle(const char title[]) {
SDL_WM_SetCaption(title, NULL);
}
void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu) {}
///////////////////////////////////////////////////////////////////////////////////////
void SkEvent::SignalNonEmptyQueue() {
SkDebugf("-------- signal nonempty\n");
post_SkEvent_event();
}
static Uint32 timer_callback(Uint32 interval) {
// SkDebugf("-------- timercallback %d\n", interval);
SkEvent::ServiceQueueTimer();
return 0;
}
void SkEvent::SignalQueueTimer(SkMSec delay)
{
SDL_SetTimer(0, NULL);
if (delay) {
SDL_SetTimer(delay, timer_callback);
}
}