From a855d6202536ff28e5aae4f22a0f31d8f5b325d0 Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Sat, 21 Jan 2017 15:18:31 -0500 Subject: Port of Duke Nukem 3D This ports Fabien Sanglard's Chocolate Duke to run on a version of SDL for Rockbox. Change-Id: I8f2c4c78af19de10c1633ed7bb7a997b43256dd9 --- apps/plugins/sdl/src/video/photon/SDL_ph_events.c | 624 ++++++++++++ .../plugins/sdl/src/video/photon/SDL_ph_events_c.h | 37 + apps/plugins/sdl/src/video/photon/SDL_ph_gl.c | 406 ++++++++ apps/plugins/sdl/src/video/photon/SDL_ph_gl.h | 41 + apps/plugins/sdl/src/video/photon/SDL_ph_image.c | 1059 ++++++++++++++++++++ apps/plugins/sdl/src/video/photon/SDL_ph_image_c.h | 59 ++ apps/plugins/sdl/src/video/photon/SDL_ph_modes.c | 390 +++++++ apps/plugins/sdl/src/video/photon/SDL_ph_modes_c.h | 43 + apps/plugins/sdl/src/video/photon/SDL_ph_mouse.c | 220 ++++ apps/plugins/sdl/src/video/photon/SDL_ph_mouse_c.h | 39 + apps/plugins/sdl/src/video/photon/SDL_ph_video.c | 648 ++++++++++++ apps/plugins/sdl/src/video/photon/SDL_ph_video.h | 157 +++ apps/plugins/sdl/src/video/photon/SDL_ph_wm.c | 118 +++ apps/plugins/sdl/src/video/photon/SDL_ph_wm_c.h | 37 + apps/plugins/sdl/src/video/photon/SDL_phyuv.c | 504 ++++++++++ apps/plugins/sdl/src/video/photon/SDL_phyuv_c.h | 62 ++ 16 files changed, 4444 insertions(+) create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_events.c create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_events_c.h create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_gl.c create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_gl.h create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_image.c create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_image_c.h create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_modes.c create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_modes_c.h create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_mouse.c create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_mouse_c.h create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_video.c create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_video.h create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_wm.c create mode 100644 apps/plugins/sdl/src/video/photon/SDL_ph_wm_c.h create mode 100644 apps/plugins/sdl/src/video/photon/SDL_phyuv.c create mode 100644 apps/plugins/sdl/src/video/photon/SDL_phyuv_c.h (limited to 'apps/plugins/sdl/src/video/photon') diff --git a/apps/plugins/sdl/src/video/photon/SDL_ph_events.c b/apps/plugins/sdl/src/video/photon/SDL_ph_events.c new file mode 100644 index 0000000000..9b7538c4b0 --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_ph_events.c @@ -0,0 +1,624 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting photon events into SDL events */ + +#include +#include +#include + +#include +#include + +#include "SDL.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ph_video.h" +#include "SDL_ph_modes_c.h" +#include "SDL_ph_image_c.h" +#include "SDL_ph_events_c.h" +#include "SDL_phyuv_c.h" + +/* The translation tables from a photon keysym to a SDL keysym */ +static SDLKey ODD_keymap[256]; +static SDLKey MISC_keymap[0xFF + 1]; +SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym); + +/* Check to see if this is a repeated key. + (idea shamelessly lifted from GII -- thanks guys! :) */ +static int ph_WarpedMotion(_THIS, PhEvent_t *winEvent) +{ + PhRect_t *rect = PhGetRects( winEvent ); + + int centre_x, centre_y; + int dx, dy; + short abs_x, abs_y; + int posted; + + centre_x = SDL_VideoSurface->w / 2; + centre_y = SDL_VideoSurface->h / 2; + + dx = rect->ul.x - centre_x; + dy = rect->ul.y - centre_y; + + posted = SDL_PrivateMouseMotion( 0, 1, dx, dy ); + + /* Move mouse cursor to middle of the window */ + PtGetAbsPosition( window, &abs_x, &abs_y ); + PhMoveCursorAbs(PhInputGroup(NULL), abs_x + centre_x, abs_y + centre_y); + + return (posted); +} + +/* Control which motion flags the window has set, a flags value of -1 sets + * MOTION_BUTTON and MOTION_NOBUTTON */ + +static void set_motion_sensitivity(_THIS, unsigned int flags) +{ + int rid; + int fields = Ph_EV_PTR_MOTION_BUTTON | Ph_EV_PTR_MOTION_NOBUTTON; + PhRegion_t region; + + if( window ) + { + rid = PtWidgetRid(window); + if( rid != 0 && PhRegionQuery(rid, ®ion, NULL, NULL, 0) == 0 ) + { + region.events_sense=(region.events_sense & ~fields)|(flags & fields); + PhRegionChange(Ph_REGION_EV_SENSE, 0, ®ion, NULL, NULL); + } + } +} + +/* Convert the photon button state value to an SDL value */ +static Uint8 ph2sdl_mousebutton(unsigned short button_state) +{ + Uint8 mouse_button = 0; + + if (button_state & Ph_BUTTON_SELECT) + mouse_button |= SDL_BUTTON_LEFT; + if (button_state & Ph_BUTTON_MENU) + mouse_button |= SDL_BUTTON_RIGHT; + if (button_state & Ph_BUTTON_ADJUST) + mouse_button |= SDL_BUTTON_MIDDLE; + + return (mouse_button); +} + +static int ph_DispatchEvent(_THIS) +{ + int posted; + PhRect_t* rect; + PhPointerEvent_t* pointerEvent; + PhKeyEvent_t* keyEvent; + PhWindowEvent_t* winEvent; + int i, buttons; + SDL_Rect sdlrects[PH_SDL_MAX_RECTS]; + + posted = 0; + + switch (phevent->type) + { + case Ph_EV_BOUNDARY: + { + if (phevent->subtype == Ph_EV_PTR_ENTER) + { + posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + } + else if (phevent->subtype ==Ph_EV_PTR_LEAVE) + { + posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + } + break; + + case Ph_EV_PTR_MOTION_BUTTON: + case Ph_EV_PTR_MOTION_NOBUTTON: + { + if (SDL_VideoSurface) + { + pointerEvent = PhGetData(phevent); + rect = PhGetRects(phevent); + + if (mouse_relative) + { + posted = ph_WarpedMotion(this, phevent); + } + else + { + posted = SDL_PrivateMouseMotion(0, 0, rect->ul.x, rect->ul.y); + } + } + } + break; + + case Ph_EV_BUT_PRESS: + { + pointerEvent = PhGetData(phevent); + buttons = ph2sdl_mousebutton(pointerEvent->buttons); + if (buttons != 0) + { + posted = SDL_PrivateMouseButton(SDL_PRESSED, buttons, 0, 0); + } + } + break; + + case Ph_EV_BUT_RELEASE: + { + pointerEvent = PhGetData(phevent); + buttons = ph2sdl_mousebutton(pointerEvent->buttons); + if (phevent->subtype == Ph_EV_RELEASE_REAL && buttons != 0) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0); + } + else if(phevent->subtype == Ph_EV_RELEASE_PHANTOM) + { + /* If the mouse is outside the window, + * only a phantom release event is sent, so + * check if the window doesn't have mouse focus. + * Not perfect, maybe checking the mouse button + * state for Ph_EV_BOUNDARY events would be + * better. */ + if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) == 0) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0); + } + } + } + break; + + case Ph_EV_WM: + { + winEvent = PhGetData(phevent); + + /* losing focus */ + if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUSLOST)) + { + set_motion_sensitivity(this, Ph_EV_PTR_MOTION_BUTTON); + posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); + } + /* gaining focus */ + else if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUS)) + { + set_motion_sensitivity(this, -1); + posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + } + /* request quit */ + else if (winEvent->event_f==Ph_WM_CLOSE) + { + posted = SDL_PrivateQuit(); + } + /* request hide/unhide */ + else if (winEvent->event_f==Ph_WM_HIDE) + { + if (currently_hided) + { + /* got unhide window event */ + /* TODO: restore application's palette if in palette mode */ + currently_hided=0; + } + else + { + /* got hide window event */ + /* TODO: restore original palette if in palette mode */ + currently_hided=1; + } + } + /* request to resize */ + else if (winEvent->event_f==Ph_WM_RESIZE) + { + currently_maximized=0; + #if (_NTO_VERSION < 630) + SDL_PrivateResize(winEvent->size.w+1, winEvent->size.h+1); + #else + /* QNX 6.3.0 have this bug fixed */ + SDL_PrivateResize(winEvent->size.w, winEvent->size.h); + #endif /* _NTO_VERSION */ + } + /* request to move */ + else if (winEvent->event_f==Ph_WM_MOVE) + { + if (current_overlay!=NULL) + { + int lockedstate=current_overlay->hwdata->locked; + int chromastate=current_overlay->hwdata->ischromakey; + int error; + SDL_Rect src, dst; + + current_overlay->hwdata->locked=1; + src.x = 0; + src.y = 0; + src.w = current_overlay->w; + src.y = current_overlay->h; + dst.x=current_overlay->hwdata->CurrentViewPort.pos.x; + dst.y=current_overlay->hwdata->CurrentViewPort.pos.y; + dst.w=current_overlay->hwdata->CurrentViewPort.size.w; + dst.h=current_overlay->hwdata->CurrentViewPort.size.h; + current_overlay->hwdata->ischromakey=0; + error=ph_DisplayYUVOverlay(this, current_overlay, &src, &dst); + if (!error) + { + current_overlay->hwdata->ischromakey=chromastate; + current_overlay->hwdata->locked=lockedstate; + } + } + } + /* maximize request */ + else if (winEvent->event_f==Ph_WM_MAX) + { + /* window already moved and resized here */ + currently_maximized=1; + } + /* restore request */ + else if (winEvent->event_f==Ph_WM_RESTORE) + { + /* window already moved and resized here */ + currently_maximized=0; + } + } + break; + + /* window has been resized, moved or removed */ + case Ph_EV_EXPOSE: + { + if (phevent->num_rects!=0) + { + int numrects; + + if (SDL_VideoSurface) + { + rect = PhGetRects(phevent); + if (phevent->num_rects>PH_SDL_MAX_RECTS) + { + /* sorry, buffers underrun, we'll update only first PH_SDL_MAX_RECTS rects */ + numrects=PH_SDL_MAX_RECTS; + } + + for(i=0; inum_rects; i++) + { + sdlrects[i].x = rect[i].ul.x; + sdlrects[i].y = rect[i].ul.y; + sdlrects[i].w = rect[i].lr.x - rect[i].ul.x + 1; + sdlrects[i].h = rect[i].lr.y - rect[i].ul.y + 1; + } + + this->UpdateRects(this, phevent->num_rects, sdlrects); + + if (current_overlay!=NULL) + { + int lockedstate=current_overlay->hwdata->locked; + int error; + SDL_Rect src, dst; + + current_overlay->hwdata->locked=1; + src.x = 0; + src.y = 0; + src.w = current_overlay->w; + src.y = current_overlay->h; + dst.x=current_overlay->hwdata->CurrentViewPort.pos.x; + dst.y=current_overlay->hwdata->CurrentViewPort.pos.y; + dst.w=current_overlay->hwdata->CurrentViewPort.size.w; + dst.h=current_overlay->hwdata->CurrentViewPort.size.h; + current_overlay->hwdata->forcedredraw=1; + error=ph_DisplayYUVOverlay(this, current_overlay, &src, &dst); + if (!error) + { + current_overlay->hwdata->forcedredraw=0; + current_overlay->hwdata->locked=lockedstate; + } + } + } + } + } + break; + + case Ph_EV_KEY: + { + SDL_keysym keysym; + + posted = 0; + + keyEvent = PhGetData(phevent); + + if (Pk_KF_Key_Down & keyEvent->key_flags) + { + /* split the wheel events from real key events */ + if ((keyEvent->key_cap==Pk_Up) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELUP, 0, 0); + break; + } + if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELDOWN, 0, 0); + break; + } + posted = SDL_PrivateKeyboard(SDL_PRESSED, ph_TranslateKey(keyEvent, &keysym)); + } + else /* must be key release */ + { + /* split the wheel events from real key events */ + if ((keyEvent->key_cap==Pk_Up) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELUP, 0, 0); + break; + } + if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELDOWN, 0, 0); + break; + } + posted = SDL_PrivateKeyboard(SDL_RELEASED, ph_TranslateKey( keyEvent, &keysym)); + } + } + break; + + case Ph_EV_INFO: + { + if (phevent->subtype==Ph_OFFSCREEN_INVALID) + { + unsigned long* EvInfoData; + + EvInfoData=(unsigned long*)PhGetData(phevent); + + switch (*EvInfoData) + { + case Pg_VIDEO_MODE_SWITCHED: + { + } + break; + case Pg_ENTERED_DIRECT: + { + } + break; + case Pg_EXITED_DIRECT: + { + } + break; + case Pg_DRIVER_STARTED: + { + } + break; + } + } + } + break; + } + + return(posted); +} + +/* perform a blocking read if no events available */ +int ph_Pending(_THIS) +{ + /* Flush the display connection and look to see if events are queued */ + PgFlush(); + + while (1) + { + switch(PhEventPeek(phevent, EVENT_SIZE)) + { + case Ph_EVENT_MSG: + return 1; + case -1: + SDL_SetError("ph_Pending(): PhEventNext failed.\n"); + return 0; + default: + return 0; + } + } + + /* Oh well, nothing is ready .. */ + return(0); +} + +void ph_PumpEvents(_THIS) +{ + /* Flush the display connection and look to see if events are queued */ + PgFlush(); + + while (ph_Pending(this)) + { + PtEventHandler(phevent); + ph_DispatchEvent(this); + } +} + +void ph_InitKeymap(void) +{ + int i; + + /* Odd keys used in international keyboards */ + for (i=0; ikey_cap; + + switch (cap>>8) + { + case 0x00: /* Latin 1 */ + case 0x01: /* Latin 2 */ + case 0x02: /* Latin 3 */ + case 0x03: /* Latin 4 */ + case 0x04: /* Katakana */ + case 0x05: /* Arabic */ + case 0x06: /* Cyrillic */ + case 0x07: /* Greek */ + case 0x08: /* Technical */ + case 0x0A: /* Publishing */ + case 0x0C: /* Hebrew */ + case 0x0D: /* Thai */ + keysym->sym = (SDLKey)(cap&0xFF); + /* Map capital letter syms to lowercase */ + if ((keysym->sym >= 'A')&&(keysym->sym <= 'Z')) + keysym->sym += ('a'-'A'); + break; + case 0xF0: + keysym->sym = MISC_keymap[cap&0xFF]; + break; + default: + keysym->sym = SDLK_UNKNOWN; + break; + } + + keysym->scancode = key->key_scan; + keysym->unicode = 0; + + if (SDL_TranslateUNICODE) + { + char utf8[MB_CUR_MAX]; + int utf8len; + wchar_t unicode; + + switch (keysym->scancode) + { + /* Esc key */ + case 0x01: keysym->unicode = 27; + break; + /* BackSpace key */ + case 0x0E: keysym->unicode = 127; + break; + /* Enter key */ + case 0x1C: keysym->unicode = 10; + break; + default: + utf8len = PhKeyToMb(utf8, key); + if (utf8len > 0) + { + utf8len = mbtowc(&unicode, utf8, utf8len); + if (utf8len > 0) + { + keysym->unicode = unicode; + } + } + break; + } + + } + + return (keysym); +} + +void ph_InitOSKeymap(_THIS) +{ + ph_InitKeymap(); +} diff --git a/apps/plugins/sdl/src/video/photon/SDL_ph_events_c.h b/apps/plugins/sdl/src/video/photon/SDL_ph_events_c.h new file mode 100644 index 0000000000..4aa939b3d9 --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_ph_events_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_EVENTS_H__ +#define __SDL_PH_EVENTS_H__ + +#include "SDL_ph_video.h" + +#define PH_SDL_MAX_RECTS 256 +#define PH_EVENT_SAFETY_POOL 512 +#define EVENT_SIZE (sizeof(PhEvent_t) + 1000 + PH_EVENT_SAFETY_POOL) + +/* Functions to be exported */ +extern void ph_InitOSKeymap(_THIS); +extern void ph_PumpEvents(_THIS); + +#endif /* __SDL_PH_EVENTS_H__ */ diff --git a/apps/plugins/sdl/src/video/photon/SDL_ph_gl.c b/apps/plugins/sdl/src/video/photon/SDL_ph_gl.c new file mode 100644 index 0000000000..3121777639 --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_ph_gl.c @@ -0,0 +1,406 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include +#include "SDL.h" +#include "SDL_ph_gl.h" + +#if SDL_VIDEO_OPENGL + +#if (_NTO_VERSION >= 630) + /* PhotonGL functions */ + GLPH_DECLARE_FUNCS; +#endif /* 6.3.0 */ + +#if (_NTO_VERSION < 630) +void ph_GL_SwapBuffers(_THIS) +{ + PgSetRegion(PtWidgetRid(window)); + PdOpenGLContextSwapBuffers(oglctx); +} +#else +void ph_GL_SwapBuffers(_THIS) +{ + qnxgl_swap_buffers(oglbuffers); +} +#endif /* 6.3.0 */ + +int ph_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) +{ + switch (attrib) + { + case SDL_GL_DOUBLEBUFFER: + *value=this->gl_config.double_buffer; + break; + case SDL_GL_STENCIL_SIZE: + *value=this->gl_config.stencil_size; + break; + case SDL_GL_DEPTH_SIZE: + *value=this->gl_config.depth_size; + break; +#if (_NTO_VERSION >= 630) + case SDL_GL_RED_SIZE: + *value=this->gl_config.red_size; + break; + case SDL_GL_GREEN_SIZE: + *value=this->gl_config.green_size; + break; + case SDL_GL_BLUE_SIZE: + *value=this->gl_config.blue_size; + break; + case SDL_GL_ALPHA_SIZE: + *value=this->gl_config.alpha_size; + break; + case SDL_GL_ACCUM_RED_SIZE: + *value=this->gl_config.accum_red_size; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + *value=this->gl_config.accum_green_size; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + *value=this->gl_config.accum_blue_size; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + *value=this->gl_config.accum_alpha_size; + break; + case SDL_GL_STEREO: + *value=this->gl_config.stereo; + break; +#endif /* 6.3.0 */ + default: + *value=0; + return(-1); + } + return 0; +} + +#if (_NTO_VERSION < 630) +int ph_GL_LoadLibrary(_THIS, const char* path) +{ + /* if code compiled with SDL_VIDEO_OPENGL, that mean that library already linked */ + this->gl_config.driver_loaded = 1; + + return 0; +} +#else +int ph_GL_LoadLibrary(_THIS, const char* path) +{ + void* handle; + int dlopen_flags=RTLD_WORLD | RTLD_GROUP; + + if (this->gl_config.dll_handle!=NULL) + { + return 0; + } + + handle = dlopen(path, dlopen_flags); + + if (handle==NULL) + { + SDL_SetError("ph_GL_LoadLibrary(): Could not load OpenGL library"); + return -1; + } + + this->gl_config.dll_handle = handle; + this->gl_config.driver_loaded = 1; + + SDL_strlcpy(this->gl_config.driver_path, path, SDL_arraysize(this->gl_config.driver_path)); + + return 0; +} +#endif /* 6.3.0 */ + +#if (_NTO_VERSION < 630) +void* ph_GL_GetProcAddress(_THIS, const char* proc) +{ + return NULL; +} +#else +void* ph_GL_GetProcAddress(_THIS, const char* proc) +{ + void* function; + + if (this->gl_config.dll_handle==NULL) + { + ph_GL_LoadLibrary(this, DEFAULT_OPENGL); + if (this->gl_config.dll_handle==NULL) + { + return NULL; + } + } + + function=qnxgl_get_func(proc, oglctx, 0); + if (function==NULL) + { + function=dlsym(this->gl_config.dll_handle, proc); + } + + return function; +} +#endif /* 6.3.0 */ + +#if (_NTO_VERSION < 630) +int ph_GL_MakeCurrent(_THIS) +{ + PgSetRegion(PtWidgetRid(window)); + + if (oglctx!=NULL) + { + PhDCSetCurrent(oglctx); + } + + return 0; +} +#else +int ph_GL_MakeCurrent(_THIS) +{ + PgSetRegion(PtWidgetRid(window)); + + if (oglctx!=NULL) + { + if (qnxgl_set_current(oglctx) == -1) + { + return -1; + } + } + + return 0; +} +#endif /* 6.3.0 */ + +#if (_NTO_VERSION < 630) + +/* This code is actual for the Photon3D Runtime which was available prior to 6.3 only */ + +int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags) +{ + PhDim_t dim; + uint64_t OGLAttrib[PH_OGL_MAX_ATTRIBS]; + int exposepost=0; + int OGLargc; + + dim.w=width; + dim.h=height; + + if ((oglctx!=NULL) && (oglflags==flags) && (oglbpp==bpp)) + { + PdOpenGLContextResize(oglctx, &dim); + PhDCSetCurrent(oglctx); + return 0; + } + else + { + if (oglctx!=NULL) + { + PhDCSetCurrent(NULL); + PhDCRelease(oglctx); + oglctx=NULL; + exposepost=1; + } + } + + OGLargc=0; + if (this->gl_config.depth_size) + { + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_DEPTH_BITS; + OGLAttrib[OGLargc++]=this->gl_config.depth_size; + } + if (this->gl_config.stencil_size) + { + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_STENCIL_BITS; + OGLAttrib[OGLargc++]=this->gl_config.stencil_size; + } + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FORCE_SW; + if (flags & SDL_FULLSCREEN) + { + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN; + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_DIRECT; + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN_BEST; + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN_CENTER; + } + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_NONE; + + if (this->gl_config.double_buffer) + { + oglctx=PdCreateOpenGLContext(2, &dim, 0, OGLAttrib); + } + else + { + oglctx=PdCreateOpenGLContext(1, &dim, 0, OGLAttrib); + } + + if (oglctx==NULL) + { + SDL_SetError("ph_SetupOpenGLContext(): cannot create OpenGL context !\n"); + return -1; + } + + PhDCSetCurrent(oglctx); + + PtFlush(); + + oglflags=flags; + oglbpp=bpp; + + if (exposepost!=0) + { + /* OpenGL context has been recreated, so report about this fact */ + SDL_PrivateExpose(); + } + + return 0; +} + +#else /* _NTO_VERSION */ + +/* This code is actual for the built-in PhGL support, which became available since 6.3 */ + +int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags) +{ + qnxgl_buf_attrib_t qnxgl_attribs[PH_OGL_MAX_ATTRIBS]; + qnxgl_buf_attrib_t* qnxgl_attribs_slide; + int num_interfaces = 0; + int num_buffers = 0; + + /* Initialize the OpenGL subsystem */ + + num_interfaces = qnxgl_init(NULL, NULL, 0); + + if (num_interfaces < 0) + { + SDL_SetError("ph_SetupOpenGLContext(): cannot initialize OpenGL subsystem !\n"); + return -1; + } + if (num_interfaces == 0) + { + SDL_SetError("ph_SetupOpenGLContext(): there are no available OpenGL renderers was found !\n"); + return -1; + } + + /* Driver is linked */ + this->gl_config.driver_loaded=1; + + /* Initialize the OpenGL context attributes */ + qnxgl_attribs_slide=qnxgl_attribs; + + /* Depth size */ + if (this->gl_config.depth_size) + { + fprintf(stderr, "setted depth size %d\n", this->gl_config.depth_size); + qnxgl_attribs_slide = qnxgl_attrib_set_depth(qnxgl_attribs_slide, this->gl_config.depth_size); + } + + /* Stencil size */ + if (this->gl_config.stencil_size) + { + qnxgl_attribs_slide = qnxgl_attrib_set_stencil(qnxgl_attribs_slide, this->gl_config.stencil_size); + } + + /* The sum of the accum bits of each channel */ + if ((this->gl_config.accum_red_size != 0) && (this->gl_config.accum_blue_size != 0) && + (this->gl_config.accum_green_size != 0)) + { + qnxgl_attribs_slide = qnxgl_attrib_set_accum(qnxgl_attribs_slide, + this->gl_config.accum_red_size + this->gl_config.accum_blue_size + + this->gl_config.accum_green_size + this->gl_config.accum_alpha_size); + } + + /* Stereo mode */ + if (this->gl_config.stereo) + { + qnxgl_attribs_slide = qnxgl_attrib_set_stereo(qnxgl_attribs_slide); + } + + /* Fullscreen mode */ + if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + qnxgl_attribs_slide = qnxgl_attrib_set_hint_fullscreen(qnxgl_attribs_slide); + } + + /* Double buffering mode */ + if (this->gl_config.double_buffer) + { + num_buffers=2; + } + else + { + num_buffers=1; + } + + /* Loading the function pointers so we can use the extensions */ + GLPH_LOAD_FUNCS_GC(oglctx); + + /* Set the buffers region to be that of our window's region */ + qnxgl_attribs_slide = glph_attrib_set_region(qnxgl_attribs_slide, PtWidgetRid(window)); + + /* End of the attributes array */ + qnxgl_attribs_slide = qnxgl_attrib_set_end(qnxgl_attribs_slide); + + /* Create the buffers with the specified color model */ + fprintf(stderr, "ARGB: %d, %d, %d, %d\n", this->gl_config.alpha_size, this->gl_config.red_size, this->gl_config.green_size, this->gl_config.blue_size); + oglbuffers = qnxgl_buffers_create( + QNXGL_FORMAT_BEST_RGB, +/* __QNXGL_BUILD_FORMAT(0, __QNXGL_COLOR_MODEL_RGB, this->gl_config.alpha_size, + this->gl_config.red_size, this->gl_config.green_size, this->gl_config.blue_size), */ + num_buffers, width, height, qnxgl_attribs, -1); + + + if (oglbuffers == NULL) + { + SDL_SetError("ph_SetupOpenGLContext(): failed to create OpenGL buffers !\n"); + qnxgl_finish(); + return -1; + } + + /* Create a QNXGL context for the previously created buffer */ + oglctx = qnxgl_context_create(oglbuffers, NULL); + + if (oglctx == NULL) + { + SDL_SetError("ph_SetupOpenGLContext(): failed to create OpenGL context !\n"); + qnxgl_buffers_destroy(oglbuffers); + qnxgl_finish(); + return -1; + } + + /* Attempt to make the context current so we can use OpenGL commands */ + if (qnxgl_set_current(oglctx) == -1) + { + SDL_SetError("ph_SetupOpenGLContext(): failed to make the OpenGL context current !\n"); + qnxgl_context_destroy(oglctx); + qnxgl_buffers_destroy(oglbuffers); + qnxgl_finish(); + return -1; + } + + PtFlush(); + + oglflags=flags; + oglbpp=bpp; + + return 0; +} + +#endif /* _NTO_VERSION */ + +#endif /* SDL_VIDEO_OPENGL */ diff --git a/apps/plugins/sdl/src/video/photon/SDL_ph_gl.h b/apps/plugins/sdl/src/video/photon/SDL_ph_gl.h new file mode 100644 index 0000000000..1fb134abf3 --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_ph_gl.h @@ -0,0 +1,41 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_GL_H__ +#define __SDL_PH_GL_H__ + +#include "SDL_ph_video.h" + +#define DEFAULT_OPENGL "/usr/lib/libGL.so" + +#if SDL_VIDEO_OPENGL + void ph_GL_SwapBuffers(_THIS); + int ph_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); + int ph_GL_LoadLibrary(_THIS, const char* path); + void* ph_GL_GetProcAddress(_THIS, const char* proc); + int ph_GL_MakeCurrent(_THIS); + + int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags); +#endif /* SDL_VIDEO_OPENGL */ + +#endif /* __SDL_PH_GL_H__ */ diff --git a/apps/plugins/sdl/src/video/photon/SDL_ph_image.c b/apps/plugins/sdl/src/video/photon/SDL_ph_image.c new file mode 100644 index 0000000000..7d64970ce6 --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_ph_image.c @@ -0,0 +1,1059 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include +#include + +#include "SDL_endian.h" +#include "SDL_video.h" +#include "../SDL_pixels_c.h" +#include "SDL_ph_video.h" +#include "SDL_ph_image_c.h" +#include "SDL_ph_modes_c.h" +#include "SDL_ph_gl.h" + +int ph_SetupImage(_THIS, SDL_Surface *screen) +{ + PgColor_t* palette=NULL; + int type=0; + int bpp; + + bpp=screen->format->BitsPerPixel; + + /* Determine image type */ + switch(bpp) + { + case 8:{ + type = Pg_IMAGE_PALETTE_BYTE; + } + break; + case 15:{ + type = Pg_IMAGE_DIRECT_555; + } + break; + case 16:{ + type = Pg_IMAGE_DIRECT_565; + } + break; + case 24:{ + type = Pg_IMAGE_DIRECT_888; + } + break; + case 32:{ + type = Pg_IMAGE_DIRECT_8888; + } + break; + default:{ + SDL_SetError("ph_SetupImage(): unsupported bpp=%d !\n", bpp); + return -1; + } + break; + } + + /* palette emulation code */ + if ((bpp==8) && (desktoppal==SDLPH_PAL_EMULATE)) + { + /* creating image palette */ + palette=SDL_malloc(_Pg_MAX_PALETTE*sizeof(PgColor_t)); + if (palette==NULL) + { + SDL_SetError("ph_SetupImage(): can't allocate memory for palette !\n"); + return -1; + } + PgGetPalette(palette); + + /* using shared memory for speed (set last param to 1) */ + if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, palette, _Pg_MAX_PALETTE, 1)) == NULL) + { + SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=8 !\n"); + SDL_free(palette); + return -1; + } + } + else + { + /* using shared memory for speed (set last param to 1) */ + if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, NULL, 0, 1)) == NULL) + { + SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=%d !\n", bpp); + return -1; + } + } + + screen->pixels = SDL_Image->image; + screen->pitch = SDL_Image->bpl; + + this->UpdateRects = ph_NormalUpdate; + + return 0; +} + +int ph_SetupOCImage(_THIS, SDL_Surface *screen) +{ + int type = 0; + int bpp; + + OCImage.flags = screen->flags; + + bpp=screen->format->BitsPerPixel; + + /* Determine image type */ + switch(bpp) + { + case 8: { + type = Pg_IMAGE_PALETTE_BYTE; + } + break; + case 15:{ + type = Pg_IMAGE_DIRECT_555; + } + break; + case 16:{ + type = Pg_IMAGE_DIRECT_565; + } + break; + case 24:{ + type = Pg_IMAGE_DIRECT_888; + } + break; + case 32:{ + type = Pg_IMAGE_DIRECT_8888; + } + break; + default:{ + SDL_SetError("ph_SetupOCImage(): unsupported bpp=%d !\n", bpp); + return -1; + } + break; + } + + /* Currently offscreen contexts with the same bit depth as display bpp only can be created */ + OCImage.offscreen_context = PdCreateOffscreenContext(0, screen->w, screen->h, Pg_OSC_MEM_PAGE_ALIGN); + + if (OCImage.offscreen_context == NULL) + { + SDL_SetError("ph_SetupOCImage(): PdCreateOffscreenContext() function failed !\n"); + return -1; + } + + screen->pitch = OCImage.offscreen_context->pitch; + + OCImage.dc_ptr = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context); + + if (OCImage.dc_ptr == NULL) + { + SDL_SetError("ph_SetupOCImage(): PdGetOffscreenContextPtr function failed !\n"); + PhDCRelease(OCImage.offscreen_context); + return -1; + } + + OCImage.FrameData0 = OCImage.dc_ptr; + OCImage.CurrentFrameData = OCImage.FrameData0; + OCImage.current = 0; + + PhDCSetCurrent(OCImage.offscreen_context); + + screen->pixels = OCImage.CurrentFrameData; + + this->UpdateRects = ph_OCUpdate; + + return 0; +} + +int ph_SetupFullScreenImage(_THIS, SDL_Surface* screen) +{ + OCImage.flags = screen->flags; + + /* Begin direct and fullscreen mode */ + if (!ph_EnterFullScreen(this, screen, PH_ENTER_DIRECTMODE)) + { + return -1; + } + + /* store palette for fullscreen */ + if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8)) + { + PgGetPalette(savedpal); + PgGetPalette(syspalph); + } + + OCImage.offscreen_context = PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY | Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_CRTC_SAFE); + if (OCImage.offscreen_context == NULL) + { + SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext() function failed !\n"); + return -1; + } + + if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) + { + OCImage.offscreen_backcontext = PdDupOffscreenContext(OCImage.offscreen_context, Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_CRTC_SAFE); + if (OCImage.offscreen_backcontext == NULL) + { + SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext(back) function failed !\n"); + return -1; + } + } + + OCImage.FrameData0 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context); + if (OCImage.FrameData0 == NULL) + { + SDL_SetError("ph_SetupFullScreenImage(): PdGetOffscreenContextPtr() function failed !\n"); + ph_DestroyImage(this, screen); + return -1; + } + + if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) + { + OCImage.FrameData1 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_backcontext); + if (OCImage.FrameData1 == NULL) + { + SDL_SetError("ph_SetupFullScreenImage(back): PdGetOffscreenContextPtr() function failed !\n"); + ph_DestroyImage(this, screen); + return -1; + } + } + + /* wait for the hardware */ + PgFlush(); + PgWaitHWIdle(); + + if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) + { + OCImage.current = 0; + PhDCSetCurrent(OCImage.offscreen_context); + screen->pitch = OCImage.offscreen_context->pitch; + screen->pixels = OCImage.FrameData0; + + /* emulate 640x400 videomode */ + if (videomode_emulatemode==1) + { + int i; + + for (i=0; i<40; i++) + { + SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + for (i=440; i<480; i++) + { + SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + screen->pixels+=screen->pitch*40; + } + PgSwapDisplay(OCImage.offscreen_backcontext, 0); + } + else + { + OCImage.current = 0; + PhDCSetCurrent(OCImage.offscreen_context); + screen->pitch = OCImage.offscreen_context->pitch; + screen->pixels = OCImage.FrameData0; + + /* emulate 640x400 videomode */ + if (videomode_emulatemode==1) + { + int i; + + for (i=0; i<40; i++) + { + SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + for (i=440; i<480; i++) + { + SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + screen->pixels+=screen->pitch*40; + } + } + + this->UpdateRects = ph_OCDCUpdate; + + /* wait for the hardware */ + PgFlush(); + PgWaitHWIdle(); + + return 0; +} + +#if SDL_VIDEO_OPENGL + +int ph_SetupOpenGLImage(_THIS, SDL_Surface* screen) +{ + this->UpdateRects = ph_OpenGLUpdate; + screen->pixels=NULL; + screen->pitch=NULL; + + #if (_NTO_VERSION >= 630) + if ((screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + if (!ph_EnterFullScreen(this, screen, PH_IGNORE_DIRECTMODE)) + { + screen->flags &= ~SDL_FULLSCREEN; + return -1; + } + } + #endif /* 6.3.0 */ + + if (ph_SetupOpenGLContext(this, screen->w, screen->h, screen->format->BitsPerPixel, screen->flags)!=0) + { + screen->flags &= ~SDL_OPENGL; + return -1; + } + + return 0; +} + +#endif /* SDL_VIDEO_OPENGL */ + +void ph_DestroyImage(_THIS, SDL_Surface* screen) +{ + +#if SDL_VIDEO_OPENGL + if ((screen->flags & SDL_OPENGL)==SDL_OPENGL) + { + if (oglctx) + { + #if (_NTO_VERSION < 630) + PhDCSetCurrent(NULL); + PhDCRelease(oglctx); + #else + qnxgl_context_destroy(oglctx); + qnxgl_buffers_destroy(oglbuffers); + qnxgl_finish(); + #endif /* 6.3.0 */ + oglctx=NULL; + oglbuffers=NULL; + oglflags=0; + oglbpp=0; + } + + #if (_NTO_VERSION >= 630) + if (currently_fullscreen) + { + ph_LeaveFullScreen(this); + } + #endif /* 6.3.0 */ + + return; + } +#endif /* SDL_VIDEO_OPENGL */ + + if (currently_fullscreen) + { + /* if we right now in 8bpp fullscreen we must release palette */ + if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8)) + { + PgSetPalette(syspalph, 0, -1, 0, 0, 0); + PgSetPalette(savedpal, 0, 0, _Pg_MAX_PALETTE, Pg_PALSET_GLOBAL | Pg_PALSET_FORCE_EXPOSE, 0); + PgFlush(); + } + ph_LeaveFullScreen(this); + } + + if (OCImage.offscreen_context != NULL) + { + PhDCRelease(OCImage.offscreen_context); + OCImage.offscreen_context = NULL; + OCImage.FrameData0 = NULL; + } + if (OCImage.offscreen_backcontext != NULL) + { + PhDCRelease(OCImage.offscreen_backcontext); + OCImage.offscreen_backcontext = NULL; + OCImage.FrameData1 = NULL; + } + OCImage.CurrentFrameData = NULL; + + if (SDL_Image) + { + /* if palette allocated, free it */ + if (SDL_Image->palette) + { + SDL_free(SDL_Image->palette); + } + PgShmemDestroy(SDL_Image->image); + SDL_free(SDL_Image); + } + + /* Must be zeroed everytime */ + SDL_Image = NULL; + + if (screen) + { + screen->pixels = NULL; + } +} + +int ph_UpdateHWInfo(_THIS) +{ + PgVideoModeInfo_t vmode; + PgHWCaps_t hwcaps; + + /* Update video ram amount */ + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + SDL_SetError("ph_UpdateHWInfo(): GetGraphicsHWCaps() function failed !\n"); + return -1; + } + this->info.video_mem=hwcaps.currently_available_video_ram/1024; + + /* obtain current mode capabilities */ + if (PgGetVideoModeInfo(hwcaps.current_video_mode, &vmode) < 0) + { + SDL_SetError("ph_UpdateHWInfo(): GetVideoModeInfo() function failed !\n"); + return -1; + } + + if ((vmode.mode_capabilities1 & PgVM_MODE_CAP1_OFFSCREEN) == PgVM_MODE_CAP1_OFFSCREEN) + { + /* this is a special test for drivers which tries to lie about offscreen capability */ + if (hwcaps.currently_available_video_ram!=0) + { + this->info.hw_available = 1; + } + else + { + this->info.hw_available = 0; + } + } + else + { + this->info.hw_available = 0; + } + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_RECTANGLE) == PgVM_MODE_CAP2_RECTANGLE) + { + this->info.blit_fill = 1; + } + else + { + this->info.blit_fill = 0; + } + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_BITBLT) == PgVM_MODE_CAP2_BITBLT) + { + this->info.blit_hw = 1; + } + else + { + this->info.blit_hw = 0; + } + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_ALPHA_BLEND) == PgVM_MODE_CAP2_ALPHA_BLEND) + { + this->info.blit_hw_A = 1; + } + else + { + this->info.blit_hw_A = 0; + } + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_CHROMA) == PgVM_MODE_CAP2_CHROMA) + { + this->info.blit_hw_CC = 1; + } + else + { + this->info.blit_hw_CC = 0; + } + + return 0; +} + +int ph_SetupUpdateFunction(_THIS, SDL_Surface* screen, Uint32 flags) +{ + int setupresult=-1; + + ph_DestroyImage(this, screen); + +#if SDL_VIDEO_OPENGL + if ((flags & SDL_OPENGL)==SDL_OPENGL) + { + setupresult=ph_SetupOpenGLImage(this, screen); + } + else + { +#endif + if ((flags & SDL_FULLSCREEN)==SDL_FULLSCREEN) + { + setupresult=ph_SetupFullScreenImage(this, screen); + } + else + { + if ((flags & SDL_HWSURFACE)==SDL_HWSURFACE) + { + setupresult=ph_SetupOCImage(this, screen); + } + else + { + setupresult=ph_SetupImage(this, screen); + } + } +#if SDL_VIDEO_OPENGL + } +#endif + if (setupresult!=-1) + { + ph_UpdateHWInfo(this); + } + + return setupresult; +} + +int ph_AllocHWSurface(_THIS, SDL_Surface* surface) +{ + PgHWCaps_t hwcaps; + + if (surface->hwdata!=NULL) + { + SDL_SetError("ph_AllocHWSurface(): hwdata already exists!\n"); + return -1; + } + surface->hwdata=SDL_malloc(sizeof(struct private_hwdata)); + SDL_memset(surface->hwdata, 0x00, sizeof(struct private_hwdata)); + surface->hwdata->offscreenctx=PdCreateOffscreenContext(0, surface->w, surface->h, Pg_OSC_MEM_PAGE_ALIGN); + if (surface->hwdata->offscreenctx == NULL) + { + SDL_SetError("ph_AllocHWSurface(): PdCreateOffscreenContext() function failed !\n"); + return -1; + } + surface->pixels=PdGetOffscreenContextPtr(surface->hwdata->offscreenctx); + if (surface->pixels==NULL) + { + PhDCRelease(surface->hwdata->offscreenctx); + SDL_SetError("ph_AllocHWSurface(): PdGetOffscreenContextPtr() function failed !\n"); + return -1; + } + surface->pitch=surface->hwdata->offscreenctx->pitch; + surface->flags|=SDL_HWSURFACE; + surface->flags|=SDL_PREALLOC; + +#if 0 /* FIXME */ + /* create simple offscreen lock */ + surface->hwdata->crlockparam.flags=0; + if (PdCreateOffscreenLock(surface->hwdata->offscreenctx, &surface->hwdata->crlockparam)!=EOK) + { + PhDCRelease(surface->hwdata->offscreenctx); + SDL_SetError("ph_AllocHWSurface(): Can't create offscreen lock !\n"); + return -1; + } +#endif /* 0 */ + + /* Update video ram amount */ + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + PdDestroyOffscreenLock(surface->hwdata->offscreenctx); + PhDCRelease(surface->hwdata->offscreenctx); + SDL_SetError("ph_AllocHWSurface(): GetGraphicsHWCaps() function failed !\n"); + return -1; + } + this->info.video_mem=hwcaps.currently_available_video_ram/1024; + + return 0; +} + +void ph_FreeHWSurface(_THIS, SDL_Surface* surface) +{ + PgHWCaps_t hwcaps; + + if (surface->hwdata==NULL) + { + SDL_SetError("ph_FreeHWSurface(): no hwdata!\n"); + return; + } + if (surface->hwdata->offscreenctx == NULL) + { + SDL_SetError("ph_FreeHWSurface(): no offscreen context to delete!\n"); + return; + } + +#if 0 /* FIXME */ + /* unlock the offscreen context if it has been locked before destroy it */ + if (PdIsOffscreenLocked(surface->hwdata->offscreenctx)==Pg_OSC_LOCKED) + { + PdUnlockOffscreen(surface->hwdata->offscreenctx); + } + + PdDestroyOffscreenLock(surface->hwdata->offscreenctx); +#endif /* 0 */ + + PhDCRelease(surface->hwdata->offscreenctx); + + SDL_free(surface->hwdata); + surface->hwdata=NULL; + + /* Update video ram amount */ + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + SDL_SetError("ph_FreeHWSurface(): GetGraphicsHWCaps() function failed !\n"); + return; + } + this->info.video_mem=hwcaps.currently_available_video_ram/1024; + + return; +} + +int ph_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + if ((src->hwdata==NULL) && (src != this->screen)) + { + SDL_SetError("ph_CheckHWBlit(): Source surface haven't hardware specific data.\n"); + src->flags&=~SDL_HWACCEL; + return -1; + } + if ((src->flags & SDL_HWSURFACE) != SDL_HWSURFACE) + { + SDL_SetError("ph_CheckHWBlit(): Source surface isn't a hardware surface.\n"); + src->flags&=~SDL_HWACCEL; + return -1; + } + + if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) + { + if (this->info.blit_hw_CC!=1) + { + src->flags&=~SDL_HWACCEL; + src->map->hw_blit=NULL; + return -1; + } + } + + if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) + { + if (this->info.blit_hw_A!=1) + { + src->flags&=~SDL_HWACCEL; + src->map->hw_blit=NULL; + return -1; + } + } + + src->flags|=SDL_HWACCEL; + src->map->hw_blit = ph_HWAccelBlit; + + return 1; +} + +PgColor_t ph_ExpandColor(_THIS, SDL_Surface* surface, Uint32 color) +{ + Uint32 truecolor; + + /* Photon API accepts true colors only during hw filling operations */ + switch(surface->format->BitsPerPixel) + { + case 8: + { + if ((surface->format->palette) && (color<=surface->format->palette->ncolors)) + { + truecolor=PgRGB(surface->format->palette->colors[color].r, + surface->format->palette->colors[color].g, + surface->format->palette->colors[color].b); + } + else + { + SDL_SetError("ph_ExpandColor(): Color out of range for the 8bpp mode !\n"); + return 0xFFFFFFFFUL; + } + } + break; + case 15: + { + truecolor = ((color & 0x00007C00UL) << 9) | /* R */ + ((color & 0x000003E0UL) << 6) | /* G */ + ((color & 0x0000001FUL) << 3) | /* B */ + ((color & 0x00007000UL) << 4) | /* R compensation */ + ((color & 0x00000380UL) << 1) | /* G compensation */ + ((color & 0x0000001CUL) >> 2); /* B compensation */ + } + break; + case 16: + { + truecolor = ((color & 0x0000F800UL) << 8) | /* R */ + ((color & 0x000007E0UL) << 5) | /* G */ + ((color & 0x0000001FUL) << 3) | /* B */ + ((color & 0x0000E000UL) << 3) | /* R compensation */ + ((color & 0x00000600UL) >> 1) | /* G compensation */ + ((color & 0x0000001CUL) >> 2); /* B compensation */ + + } + break; + case 24: + { + truecolor=color & 0x00FFFFFFUL; + } + break; + case 32: + { + truecolor=color; + } + break; + default: + { + SDL_SetError("ph_ExpandColor(): Unsupported depth for the hardware operations !\n"); + return 0xFFFFFFFFUL; + } + } + + return truecolor; +} + +int ph_FillHWRect(_THIS, SDL_Surface* surface, SDL_Rect* rect, Uint32 color) +{ + PgColor_t oldcolor; + Uint32 truecolor; + int ydisp=0; + + if (this->info.blit_fill!=1) + { + return -1; + } + + truecolor=ph_ExpandColor(this, surface, color); + if (truecolor==0xFFFFFFFFUL) + { + return -1; + } + + oldcolor=PgSetFillColor(truecolor); + + /* 640x400 videomode emulation */ + if (videomode_emulatemode==1) + { + ydisp+=40; + } + + PgDrawIRect(rect->x, rect->y+ydisp, rect->w+rect->x-1, rect->h+rect->y+ydisp-1, Pg_DRAW_FILL); + PgSetFillColor(oldcolor); + PgFlush(); + PgWaitHWIdle(); + + return 0; +} + +int ph_FlipHWSurface(_THIS, SDL_Surface* screen) +{ + PhArea_t farea; + + if ((screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + /* flush all drawing ops before blitting */ + PgFlush(); + PgWaitHWIdle(); + + farea.pos.x=0; + farea.pos.y=0; + farea.size.w=screen->w; + farea.size.h=screen->h; + + /* emulate 640x400 videomode */ + if (videomode_emulatemode==1) + { + farea.pos.y+=40; + } + + PgContextBlitArea(OCImage.offscreen_context, &farea, OCImage.offscreen_backcontext, &farea); + + /* flush the blitting */ + PgFlush(); + PgWaitHWIdle(); + } + return 0; +} + +int ph_LockHWSurface(_THIS, SDL_Surface* surface) +{ + +#if 0 /* FIXME */ + int lockresult; + + if (surface->hwdata == NULL) + { + return; + } + + surface->hwdata->lockparam.flags=0; + surface->hwdata->lockparam.time_out=NULL; + lockresult=PdLockOffscreen(surface->hwdata->offscreenctx, &surface->hwdata->lockparam); + + switch (lockresult) + { + case EOK: + break; + case Pg_OSC_LOCK_DEADLOCK: + SDL_SetError("ph_LockHWSurface(): Deadlock detected !\n"); + return -1; + case Pg_OSC_LOCK_INVALID: + SDL_SetError("ph_LockHWSurface(): Lock invalid !\n"); + return -1; + default: + SDL_SetError("ph_LockHWSurface(): Can't lock the surface !\n"); + return -1; + } +#endif /* 0 */ + + return 0; +} + +void ph_UnlockHWSurface(_THIS, SDL_Surface* surface) +{ + +#if 0 /* FIXME */ + int unlockresult; + + if ((surface == NULL) || (surface->hwdata == NULL)) + { + return; + } + + if (PdIsOffscreenLocked(surface->hwdata->offscreenctx)==Pg_OSC_LOCKED) + { + unlockresult=PdUnlockOffscreen(surface->hwdata->offscreenctx); + } +#endif /* 0 */ + + return; +} + +int ph_HWAccelBlit(SDL_Surface* src, SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect) +{ + SDL_VideoDevice* this=current_video; + PhArea_t srcarea; + PhArea_t dstarea; + int ydisp=0; + + /* 640x400 videomode emulation */ + if (videomode_emulatemode==1) + { + ydisp+=40; + } + + srcarea.pos.x=srcrect->x; + srcarea.pos.y=srcrect->y; + srcarea.size.w=srcrect->w; + srcarea.size.h=srcrect->h; + + dstarea.pos.x=dstrect->x; + dstarea.pos.y=dstrect->y; + dstarea.size.w=dstrect->w; + dstarea.size.h=dstrect->h; + + if (((src == this->screen) || (src->hwdata!=NULL)) && ((dst == this->screen) || (dst->hwdata!=NULL))) + { + if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) + { + ph_SetHWColorKey(this, src, src->format->colorkey); + PgChromaOn(); + } + + if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) + { + ph_SetHWAlpha(this, src, src->format->alpha); + PgAlphaOn(); + } + + if (dst == this->screen) + { + if (src == this->screen) + { + /* blitting from main screen to main screen */ + dstarea.pos.y+=ydisp; + srcarea.pos.y+=ydisp; + PgContextBlitArea(OCImage.offscreen_context, &srcarea, OCImage.offscreen_context, &dstarea); + } + else + { + /* blitting from offscreen to main screen */ + dstarea.pos.y+=ydisp; + PgContextBlitArea(src->hwdata->offscreenctx, &srcarea, OCImage.offscreen_context, &dstarea); + } + } + else + { + if (src == this->screen) + { + /* blitting from main screen to offscreen */ + srcarea.pos.y+=ydisp; + PgContextBlitArea(OCImage.offscreen_context, &srcarea, dst->hwdata->offscreenctx, &dstarea); + } + else + { + /* blitting offscreen to offscreen */ + PgContextBlitArea(src->hwdata->offscreenctx, &srcarea, dst->hwdata->offscreenctx, &dstarea); + } + } + + if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) + { + PgAlphaOff(); + } + + if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) + { + PgChromaOff(); + } + } + else + { + SDL_SetError("ph_HWAccelBlit(): Source or target surface is not a hardware surface !\n"); + return -1; + } + + PgFlush(); + PgWaitHWIdle(); + + return 0; +} + +int ph_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + if (this->info.blit_hw_CC!=1) + { + return -1; + } + + if (surface->hwdata!=NULL) + { + surface->hwdata->colorkey=ph_ExpandColor(this, surface, key); + if (surface->hwdata->colorkey==0xFFFFFFFFUL) + { + return -1; + } + } + PgSetChroma(surface->hwdata->colorkey, Pg_CHROMA_SRC_MATCH | Pg_CHROMA_NODRAW); + + return 0; +} + +int ph_SetHWAlpha(_THIS, SDL_Surface* surface, Uint8 alpha) +{ + if (this->info.blit_hw_A!=1) + { + return -1; + } + + PgSetAlphaBlend(NULL, alpha); + + return 0; +} + +#if SDL_VIDEO_OPENGL +void ph_OpenGLUpdate(_THIS, int numrects, SDL_Rect* rects) +{ + this->GL_SwapBuffers(this); + + return; +} +#endif /* SDL_VIDEO_OPENGL */ + +void ph_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + PhPoint_t ph_pos; + PhRect_t ph_rect; + int i; + + for (i=0; iBitsPerPixel) + { + Amodelist[j].w = mode_info.width; + Amodelist[j].h = mode_info.height; + Amodelist[j].x = 0; + Amodelist[j].y = 0; + j++; + } + } + + /* reorder biggest for smallest, assume width dominates */ + + for(i=0; iflags & SDL_ANYFORMAT) + { + if ((mode = get_mode_any_format(screen->w, screen->h, screen->format->BitsPerPixel)) == 0) + { + SDL_SetError("ph_EnterFullScreen(): can't find appropriate video mode !\n"); + return 0; + } + } + else + { + if ((mode = ph_GetVideoMode(screen->w, screen->h, screen->format->BitsPerPixel)) == 0) + { + SDL_SetError("ph_EnterFullScreen(): can't find appropriate video mode !\n"); + return 0; + } + if (PgGetVideoModeInfo(mode, &mode_info) < 0) + { + SDL_SetError("ph_EnterFullScreen(): can't get video mode capabilities !\n"); + return 0; + } + if (mode_info.height != screen->h) + { + if ((mode_info.height==480) && (screen->h==400)) + { + videomode_emulatemode=1; + } + } + else + { + videomode_emulatemode=0; + } + } + + /* save old video mode caps */ + PgGetVideoMode(&settings); + old_video_mode=settings.mode; + old_refresh_rate=settings.refresh; + + /* setup new video mode */ + settings.mode = mode; + settings.refresh = 0; + settings.flags = 0; + + refreshrate=SDL_getenv("SDL_PHOTON_FULLSCREEN_REFRESH"); + if (refreshrate!=NULL) + { + if (SDL_sscanf(refreshrate, "%d", &refreshratenum)==1) + { + settings.refresh = refreshratenum; + } + } + + if (PgSetVideoMode(&settings) < 0) + { + SDL_SetError("ph_EnterFullScreen(): PgSetVideoMode() call failed !\n"); + return 0; + } + + if (this->screen) + { + if ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL) + { +#if !SDL_VIDEO_OPENGL || (_NTO_VERSION < 630) + return 0; /* 6.3.0 */ +#endif + } + } + + if (fmode==0) + { + if (OCImage.direct_context==NULL) + { + OCImage.direct_context=(PdDirectContext_t*)PdCreateDirectContext(); + if (!OCImage.direct_context) + { + SDL_SetError("ph_EnterFullScreen(): Can't create direct context !\n"); + ph_LeaveFullScreen(this); + return 0; + } + } + OCImage.oldDC=PdDirectStart(OCImage.direct_context); + } + + currently_fullscreen = 1; + } + PgFlush(); + + return 1; +} + +int ph_LeaveFullScreen(_THIS) +{ + PgDisplaySettings_t oldmode_settings; + + if (currently_fullscreen) + { + if ((this->screen) && ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL)) + { +#if !SDL_VIDEO_OPENGL || (_NTO_VERSION < 630) + return 0; +#endif + } + + /* release routines starts here */ + { + if (OCImage.direct_context) + { + PdDirectStop(OCImage.direct_context); + PdReleaseDirectContext(OCImage.direct_context); + OCImage.direct_context=NULL; + } + if (OCImage.oldDC) + { + PhDCSetCurrent(OCImage.oldDC); + OCImage.oldDC=NULL; + } + + currently_fullscreen=0; + + /* Restore old video mode */ + if (old_video_mode != -1) + { + oldmode_settings.mode = (unsigned short) old_video_mode; + oldmode_settings.refresh = (unsigned short) old_refresh_rate; + oldmode_settings.flags = 0; + + if (PgSetVideoMode(&oldmode_settings) < 0) + { + SDL_SetError("Ph_LeaveFullScreen(): PgSetVideoMode() function failed !\n"); + return 0; + } + } + + old_video_mode=-1; + old_refresh_rate=-1; + } + } + return 1; +} diff --git a/apps/plugins/sdl/src/video/photon/SDL_ph_modes_c.h b/apps/plugins/sdl/src/video/photon/SDL_ph_modes_c.h new file mode 100644 index 0000000000..117c5a3a91 --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_ph_modes_c.h @@ -0,0 +1,43 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_MODES_H__ +#define __SDL_PH_MODES_H__ + +#include "SDL_ph_video.h" + +#define PH_MAX_VIDEOMODES 127 + +#define PH_ENTER_DIRECTMODE 0 +#define PH_IGNORE_DIRECTMODE 1 + +extern SDL_Rect **ph_ListModes(_THIS,SDL_PixelFormat *format, Uint32 flags); +extern void ph_FreeVideoModes(_THIS); +extern int ph_ResizeFullScreen(_THIS); +extern int ph_EnterFullScreen(_THIS, SDL_Surface* screen, int fmode); +extern int ph_LeaveFullScreen(_THIS); +extern int ph_GetVideoMode(int width, int height, int bpp); +extern int get_mode_any_format(int width, int height, int bpp); +extern int ph_ToggleFullScreen(_THIS, int on); + +#endif /* __SDL_PH_MODES_H__ */ diff --git a/apps/plugins/sdl/src/video/photon/SDL_ph_mouse.c b/apps/plugins/sdl/src/video/photon/SDL_ph_mouse.c new file mode 100644 index 0000000000..a25aa1fc85 --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_ph_mouse.c @@ -0,0 +1,220 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_ph_mouse_c.h" + +struct WMcursor +{ + PhCursorDef_t *ph_cursor ; +}; + +void ph_FreeWMCursor(_THIS, WMcursor *cursor) +{ + if (window != NULL) + { + SDL_Lock_EventThread(); + + if (PtSetResource(window, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_INHERIT, 0) < 0) + { + /* TODO: output error msg */ + } + + SDL_Unlock_EventThread(); + } + + SDL_free(cursor); +} + +WMcursor *ph_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor* cursor; + int clen, i; + unsigned char bit, databit, maskbit; + + /* Allocate and initialize the cursor memory */ + if ((cursor = (WMcursor*)SDL_malloc(sizeof(WMcursor))) == NULL) + { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(cursor,0,sizeof(WMcursor)); + + cursor->ph_cursor = (PhCursorDef_t *) SDL_malloc(sizeof(PhCursorDef_t) + 32*4*2); + + if (cursor->ph_cursor == NULL) + { + SDL_SetError("ph_CreateWMCursor(): cursor malloc failed !\n"); + return NULL; + } + + SDL_memset(cursor->ph_cursor,0,(sizeof(PhCursorDef_t) + 32*4*2)); + + cursor->ph_cursor->hdr.type =Ph_RDATA_CURSOR; + cursor->ph_cursor->size1.x = (short)w; + cursor->ph_cursor->size1.y = (short)h; + cursor->ph_cursor->offset1.x = (short)hot_x; + cursor->ph_cursor->offset1.y = (short)hot_y; + cursor->ph_cursor->bytesperline1 = (char)w/8; + cursor->ph_cursor->color1 = Pg_WHITE; + cursor->ph_cursor->size2.x = (short)w; + cursor->ph_cursor->size2.y = (short)h; + cursor->ph_cursor->offset2.x = (short)hot_x; + cursor->ph_cursor->offset2.y = (short)hot_y; + cursor->ph_cursor->bytesperline2 = (char)w/8; + cursor->ph_cursor->color2 = Pg_BLACK; + + clen = (w/8)*h; + + /* Copy the mask and the data to different bitmap planes */ + for (i=0; iph_cursor->images[i] |= (databit == 0) ? maskbit : 0; + /* If the databit != 0, treat it as a black pixel and + * ignore the maskbit (can't do an inverted color) */ + cursor->ph_cursor->images[i+clen] |= databit; + } + } + + /* #bytes following the hdr struct */ + cursor->ph_cursor->hdr.len =sizeof(PhCursorDef_t) + clen*2 - sizeof(PhRegionDataHdr_t); + + return (cursor); +} + +PhCursorDef_t ph_GetWMPhCursor(WMcursor *cursor) +{ + return (*cursor->ph_cursor); +} + +int ph_ShowWMCursor(_THIS, WMcursor* cursor) +{ + PtArg_t args[3]; + int nargs = 0; + + /* Don't do anything if the display is gone */ + if (window == NULL) + { + return (0); + } + + /* looks like photon can't draw mouse cursor in direct mode */ + if ((this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + /* disable the fake mouse in the fullscreen OpenGL mode */ + if ((this->screen->flags & SDL_OPENGL) == SDL_OPENGL) + { + cursor=NULL; + } + else + { + return (0); + } + } + + /* Set the photon cursor, or blank if cursor is NULL */ + if (cursor!=NULL) + { + PtSetArg(&args[0], Pt_ARG_CURSOR_TYPE, Ph_CURSOR_BITMAP, 0); + /* Could set next to any PgColor_t value */ + PtSetArg(&args[1], Pt_ARG_CURSOR_COLOR, Ph_CURSOR_DEFAULT_COLOR , 0); + PtSetArg(&args[2], Pt_ARG_BITMAP_CURSOR, cursor->ph_cursor, (cursor->ph_cursor->hdr.len + sizeof(PhRegionDataHdr_t))); + nargs = 3; + } + else /* Ph_CURSOR_NONE */ + { + PtSetArg(&args[0], Pt_ARG_CURSOR_TYPE, Ph_CURSOR_NONE, 0); + nargs = 1; + } + + SDL_Lock_EventThread(); + + if (PtSetResources(window, nargs, args) < 0 ) + { + return (0); + } + + SDL_Unlock_EventThread(); + + return (1); +} + + +void ph_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + short abs_x, abs_y; + + SDL_Lock_EventThread(); + PtGetAbsPosition( window, &abs_x, &abs_y ); + PhMoveCursorAbs( PhInputGroup(NULL), x + abs_x, y + abs_y ); + SDL_Unlock_EventThread(); +} + + +void ph_CheckMouseMode(_THIS) +{ + /* If the mouse is hidden and input is grabbed, we use relative mode */ + if ( !(SDL_cursorstate & CURSOR_VISIBLE) && (this->input_grab != SDL_GRAB_OFF)) + { + mouse_relative = 1; + } + else + { + mouse_relative = 0; + } +} + + +void ph_UpdateMouse(_THIS) +{ + PhCursorInfo_t phcursor; + short abs_x; + short abs_y; + + /* Lock the event thread, in multi-threading environments */ + SDL_Lock_EventThread(); + + /* synchronizing photon mouse cursor position and SDL mouse position, if cursor appears over window. */ + PtGetAbsPosition(window, &abs_x, &abs_y); + PhQueryCursor(PhInputGroup(NULL), &phcursor); + if (((phcursor.pos.x >= abs_x) && (phcursor.pos.x <= abs_x + this->screen->w)) && + ((phcursor.pos.y >= abs_y) && (phcursor.pos.y <= abs_y + this->screen->h))) + { + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_PrivateMouseMotion(0, 0, phcursor.pos.x-abs_x, phcursor.pos.y-abs_y); + } + else + { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + + /* Unlock the event thread, in multi-threading environments */ + SDL_Unlock_EventThread(); +} diff --git a/apps/plugins/sdl/src/video/photon/SDL_ph_mouse_c.h b/apps/plugins/sdl/src/video/photon/SDL_ph_mouse_c.h new file mode 100644 index 0000000000..55a92b606b --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_ph_mouse_c.h @@ -0,0 +1,39 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_MOUSE_H__ +#define __SDL_PH_MOUSE_H__ + +#include "SDL_ph_video.h" + +/* Functions to be exported */ +extern void ph_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *ph_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern PhCursorDef_t ph_GetWMPhCursor(WMcursor *cursor); +extern int ph_ShowWMCursor(_THIS, WMcursor *cursor); +extern void ph_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +extern void ph_CheckMouseMode(_THIS); +extern void ph_UpdateMouse(_THIS); + +#endif /* __SDL_PH_MOUSE_H__ */ diff --git a/apps/plugins/sdl/src/video/photon/SDL_ph_video.c b/apps/plugins/sdl/src/video/photon/SDL_ph_video.c new file mode 100644 index 0000000000..5e1a82b0ea --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_ph_video.c @@ -0,0 +1,648 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include +#include + +#include "SDL_endian.h" +#include "SDL_timer.h" +#include "SDL_thread.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ph_video.h" +#include "SDL_ph_modes_c.h" +#include "SDL_ph_image_c.h" +#include "SDL_ph_events_c.h" +#include "SDL_ph_mouse_c.h" +#include "SDL_ph_wm_c.h" +#include "SDL_ph_gl.h" +#include "SDL_phyuv_c.h" +#include "../blank_cursor.h" + +static int ph_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Surface *ph_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int ph_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void ph_VideoQuit(_THIS); +static void ph_DeleteDevice(SDL_VideoDevice *device); + +static int phstatus=-1; + +static int ph_Available(void) +{ + if (phstatus!=0) + { + phstatus=PtInit(NULL); + if (phstatus==0) + { + return 1; + } + else + { + return 0; + } + } + return 1; +} + +static SDL_VideoDevice* ph_CreateDevice(int devindex) +{ + SDL_VideoDevice* device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if (device) + { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData*)SDL_malloc((sizeof *device->hidden)); + device->gl_data = NULL; + } + if ((device == NULL) || (device->hidden == NULL)) + { + SDL_OutOfMemory(); + ph_DeleteDevice(device); + return NULL; + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the driver flags */ + device->handles_any_size = 1; + + /* Set the function pointers */ + device->CreateYUVOverlay = ph_CreateYUVOverlay; + device->VideoInit = ph_VideoInit; + device->ListModes = ph_ListModes; + device->SetVideoMode = ph_SetVideoMode; + device->ToggleFullScreen = ph_ToggleFullScreen; + device->UpdateMouse = ph_UpdateMouse; + device->SetColors = ph_SetColors; + device->UpdateRects = NULL; /* set up in ph_SetupUpdateFunction */ + device->VideoQuit = ph_VideoQuit; + device->AllocHWSurface = ph_AllocHWSurface; + device->CheckHWBlit = ph_CheckHWBlit; + device->FillHWRect = ph_FillHWRect; + device->SetHWColorKey = ph_SetHWColorKey; + device->SetHWAlpha = ph_SetHWAlpha; + device->LockHWSurface = ph_LockHWSurface; + device->UnlockHWSurface = ph_UnlockHWSurface; + device->FlipHWSurface = ph_FlipHWSurface; + device->FreeHWSurface = ph_FreeHWSurface; + device->SetCaption = ph_SetCaption; + device->SetIcon = NULL; + device->IconifyWindow = ph_IconifyWindow; + device->GrabInput = ph_GrabInput; + device->GetWMInfo = ph_GetWMInfo; + device->FreeWMCursor = ph_FreeWMCursor; + device->CreateWMCursor = ph_CreateWMCursor; + device->ShowWMCursor = ph_ShowWMCursor; + device->WarpWMCursor = ph_WarpWMCursor; + device->MoveWMCursor = NULL; + device->CheckMouseMode = ph_CheckMouseMode; + device->InitOSKeymap = ph_InitOSKeymap; + device->PumpEvents = ph_PumpEvents; + + /* OpenGL support. */ +#if SDL_VIDEO_OPENGL + device->GL_MakeCurrent = ph_GL_MakeCurrent; + device->GL_SwapBuffers = ph_GL_SwapBuffers; + device->GL_GetAttribute = ph_GL_GetAttribute; + device->GL_LoadLibrary = ph_GL_LoadLibrary; + device->GL_GetProcAddress = ph_GL_GetProcAddress; +#endif /* SDL_VIDEO_OPENGL */ + + device->free = ph_DeleteDevice; + + return device; +} + +VideoBootStrap ph_bootstrap = { + "photon", "QNX Photon video output", + ph_Available, ph_CreateDevice +}; + +static void ph_DeleteDevice(SDL_VideoDevice *device) +{ + if (device) + { + if (device->hidden) + { + SDL_free(device->hidden); + device->hidden = NULL; + } + if (device->gl_data) + { + SDL_free(device->gl_data); + device->gl_data = NULL; + } + SDL_free(device); + device = NULL; + } +} + +static PtWidget_t *ph_CreateWindow(_THIS) +{ + PtWidget_t *widget; + + widget = PtCreateWidget(PtWindow, NULL, 0, NULL); + + return widget; +} + +static int ph_SetupWindow(_THIS, int w, int h, int flags) +{ + PtArg_t args[32]; + PhPoint_t pos = {0, 0}; + PhDim_t* olddim; + PhDim_t dim = {w, h}; + PhRect_t desktopextent; + int nargs = 0; + const char* windowpos; + const char* iscentered; + int x, y; + + /* check if window size has been changed by Window Manager */ + PtGetResource(window, Pt_ARG_DIM, &olddim, 0); + if ((olddim->w!=w) || (olddim->h!=h)) + { + PtSetArg(&args[nargs++], Pt_ARG_DIM, &dim, 0); + } + + if ((flags & SDL_RESIZABLE) == SDL_RESIZABLE) + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE, Ph_WM_MAX | Ph_WM_RESTORE | Ph_WM_RESIZE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, Ph_WM_RESIZE | Ph_WM_MOVE | Ph_WM_CLOSE | Ph_WM_MAX | Ph_WM_RESTORE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE, Ph_WM_RENDER_RESIZE | Ph_WM_RENDER_MAX | Ph_WM_RENDER_COLLAPSE | Ph_WM_RENDER_RETURN); + PtSetArg(&args[nargs++], Pt_ARG_RESIZE_FLAGS, Pt_TRUE, Pt_RESIZE_XY_AS_REQUIRED); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_RESIZE | Ph_WM_MAX | Ph_WM_RESTORE | Ph_WM_CLOSE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_FALSE, Ph_WM_RESIZE | Ph_WM_MAX | Ph_WM_RESTORE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, Ph_WM_MOVE | Ph_WM_CLOSE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Ph_WM_RENDER_RESIZE | Ph_WM_RENDER_MAX | Ph_WM_RENDER_COLLAPSE | Ph_WM_RENDER_RETURN); + PtSetArg(&args[nargs++], Pt_ARG_RESIZE_FLAGS, Pt_FALSE, Pt_RESIZE_XY_AS_REQUIRED); + } + + if (((flags & SDL_NOFRAME)==SDL_NOFRAME) || ((flags & SDL_FULLSCREEN)==SDL_FULLSCREEN)) + { + if ((flags & SDL_RESIZABLE) != SDL_RESIZABLE) + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Pt_TRUE); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Pt_TRUE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE, Ph_WM_RENDER_RESIZE | Ph_WM_RENDER_BORDER); + } + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE, Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE | + Ph_WM_RENDER_CLOSE | Ph_WM_RENDER_MENU | Ph_WM_RENDER_MIN); + } + + if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + PtSetArg(&args[nargs++], Pt_ARG_POS, &pos, 0); + PtSetArg(&args[nargs++], Pt_ARG_BASIC_FLAGS, Pt_TRUE, Pt_BASIC_PREVENT_FILL); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE, Ph_WM_FFRONT | Ph_WM_MAX | Ph_WM_TOFRONT | Ph_WM_CONSWITCH); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISFRONT | Ph_WM_STATE_ISFOCUS | Ph_WM_STATE_ISALTKEY); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_FFRONT | Ph_WM_CONSWITCH); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISFRONT); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISALTKEY); + + if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE) + { + PtSetArg(&args[nargs++], Pt_ARG_BASIC_FLAGS, Pt_TRUE, Pt_BASIC_PREVENT_FILL); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_FILL_COLOR, Pg_BLACK, 0); + } + if (!currently_maximized) + { + windowpos = SDL_getenv("SDL_VIDEO_WINDOW_POS"); + iscentered = SDL_getenv("SDL_VIDEO_CENTERED"); + + if ((iscentered) || ((windowpos) && (SDL_strcmp(windowpos, "center")==0))) + { + PhWindowQueryVisible(Ph_QUERY_CONSOLE, 0, 0, &desktopextent); + if (desktop_mode.width>w) + { + pos.x = (desktop_mode.width - w)/2; + } + if (desktop_mode.height>h) + { + pos.y = (desktop_mode.height - h)/2; + } + + pos.x+=desktopextent.ul.x; + pos.y+=desktopextent.ul.y; + PtSetArg(&args[nargs++], Pt_ARG_POS, &pos, 0); + } + else + { + if (windowpos) + { + if (SDL_sscanf(windowpos, "%d,%d", &x, &y) == 2) + { + if ((xw, olddim->h); +#endif + + return 0; +} + +static const struct ColourMasks* ph_GetColourMasks(int bpp) +{ + /* The alpha mask doesn't appears to be needed */ + static const struct ColourMasks phColorMasks[5] = { + /* 8 bit */ {0, 0, 0, 0, 8}, + /* 15 bit ARGB */ {0x7C00, 0x03E0, 0x001F, 0x8000, 15}, + /* 16 bit RGB */ {0xF800, 0x07E0, 0x001F, 0x0000, 16}, + /* 24 bit RGB */ {0xFF0000, 0x00FF00, 0x0000FF, 0x000000, 24}, + /* 32 bit ARGB */ {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, 32}, + }; + + switch (bpp) + { + case 8: + return &phColorMasks[0]; + case 15: + return &phColorMasks[1]; + case 16: + return &phColorMasks[2]; + case 24: + return &phColorMasks[3]; + case 32: + return &phColorMasks[4]; + } + return NULL; +} + +static int ph_VideoInit(_THIS, SDL_PixelFormat* vformat) +{ + PgHWCaps_t hwcaps; + int i; + + window=NULL; + desktoppal=SDLPH_PAL_NONE; + +#if SDL_VIDEO_OPENGL + oglctx=NULL; + oglbuffers=NULL; + oglflags=0; + oglbpp=0; +#endif + + old_video_mode=-1; + old_refresh_rate=-1; + + if (NULL == (phevent = SDL_malloc(EVENT_SIZE))) + { + SDL_OutOfMemory(); + return -1; + } + SDL_memset(phevent, 0x00, EVENT_SIZE); + + window = ph_CreateWindow(this); + if (window == NULL) + { + SDL_SetError("ph_VideoInit(): Couldn't create video window !\n"); + return -1; + } + + /* Create the blank cursor */ + SDL_BlankCursor = this->CreateWMCursor(this, blank_cdata, blank_cmask, + (int)BLANK_CWIDTH, (int)BLANK_CHEIGHT, + (int)BLANK_CHOTX, (int)BLANK_CHOTY); + + if (SDL_BlankCursor == NULL) + { + return -1; + } + + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + SDL_SetError("ph_VideoInit(): GetGraphicsHWCaps function failed !\n"); + this->FreeWMCursor(this, SDL_BlankCursor); + return -1; + } + + if (PgGetVideoModeInfo(hwcaps.current_video_mode, &desktop_mode) < 0) + { + SDL_SetError("ph_VideoInit(): PgGetVideoModeInfo function failed !\n"); + this->FreeWMCursor(this, SDL_BlankCursor); + return -1; + } + + /* Determine the current screen size */ + this->info.current_w = desktop_mode.width; + this->info.current_h = desktop_mode.height; + + /* We need to return BytesPerPixel as it in used by CreateRGBsurface */ + vformat->BitsPerPixel = desktop_mode.bits_per_pixel; + vformat->BytesPerPixel = desktop_mode.bytes_per_scanline/desktop_mode.width; + desktopbpp = desktop_mode.bits_per_pixel; + + /* save current palette */ + if (desktopbpp==8) + { + PgGetPalette(savedpal); + PgGetPalette(syspalph); + } + else + { + for(i=0; i<_Pg_MAX_PALETTE; i++) + { + savedpal[i]=PgRGB(0, 0, 0); + syspalph[i]=PgRGB(0, 0, 0); + } + } + + currently_fullscreen = 0; + currently_hided = 0; + currently_maximized = 0; + current_overlay = NULL; + + OCImage.direct_context = NULL; + OCImage.offscreen_context = NULL; + OCImage.offscreen_backcontext = NULL; + OCImage.oldDC = NULL; + OCImage.CurrentFrameData = NULL; + OCImage.FrameData0 = NULL; + OCImage.FrameData1 = NULL; + videomode_emulatemode = 0; + + this->info.wm_available = 1; + + ph_UpdateHWInfo(this); + + return 0; +} + +static SDL_Surface* ph_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) +{ + const struct ColourMasks* mask; + + /* Lock the event thread, in multi-threading environments */ + SDL_Lock_EventThread(); + + current->flags = flags; + + /* if we do not have desired fullscreen mode, then fallback into window mode */ + if (((current->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) && (ph_GetVideoMode(width, height, bpp)==0)) + { + current->flags &= ~SDL_FULLSCREEN; + current->flags &= ~SDL_NOFRAME; + current->flags &= ~SDL_RESIZABLE; + } + + ph_SetupWindow(this, width, height, current->flags); + + mask = ph_GetColourMasks(bpp); + if (mask != NULL) + { + SDL_ReallocFormat(current, mask->bpp, mask->red, mask->green, mask->blue, 0); + } + else + { + SDL_SetError("ph_SetVideoMode(): desired bpp is not supported by photon !\n"); + return NULL; + } + + if ((current->flags & SDL_OPENGL)==SDL_OPENGL) + { +#if !SDL_VIDEO_OPENGL + /* if no built-in OpenGL support */ + SDL_SetError("ph_SetVideoMode(): no OpenGL support, you need to recompile SDL.\n"); + current->flags &= ~SDL_OPENGL; + return NULL; +#endif /* SDL_VIDEO_OPENGL */ + } + else + { + /* Initialize internal variables */ + if ((current->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + if (bpp==8) + { + desktoppal=SDLPH_PAL_SYSTEM; + } + + current->flags &= ~SDL_RESIZABLE; /* no resize for Direct Context */ + current->flags |= SDL_HWSURFACE; + } + else + { + /* remove this if we'll have support for the non-fullscreen sw/hw+doublebuf one day */ + current->flags &= ~SDL_DOUBLEBUF; + + /* Use offscreen memory if SDL_HWSURFACE flag is set */ + if ((current->flags & SDL_HWSURFACE) == SDL_HWSURFACE) + { + if (desktopbpp!=bpp) + { + current->flags &= ~SDL_HWSURFACE; + } + } + + /* using palette emulation code in window mode */ + if (bpp==8) + { + if (desktopbpp>=15) + { + desktoppal = SDLPH_PAL_EMULATE; + } + else + { + desktoppal = SDLPH_PAL_SYSTEM; + } + } + else + { + desktoppal = SDLPH_PAL_NONE; + } + } + } + + current->w = width; + current->h = height; + + if (desktoppal==SDLPH_PAL_SYSTEM) + { + current->flags|=SDL_HWPALETTE; + } + + /* Must call at least once for setup image planes */ + if (ph_SetupUpdateFunction(this, current, current->flags)==-1) + { + /* Error string was filled in the ph_SetupUpdateFunction() */ + return NULL; + } + + /* finish window drawing, if we are not in fullscreen, of course */ + if ((current->flags & SDL_FULLSCREEN) != SDL_FULLSCREEN) + { + PtFlush(); + } + else + { + PgFlush(); + } + + visualbpp=bpp; + + ph_UpdateHWInfo(this); + + SDL_Unlock_EventThread(); + + /* We've done! */ + return (current); +} + +static void ph_VideoQuit(_THIS) +{ + /* restore palette */ + if (desktopbpp==8) + { + PgSetPalette(syspalph, 0, -1, 0, 0, 0); + PgSetPalette(savedpal, 0, 0, _Pg_MAX_PALETTE, Pg_PALSET_GLOBAL | Pg_PALSET_FORCE_EXPOSE, 0); + PgFlush(); + } + + ph_DestroyImage(this, SDL_VideoSurface); + + if (window) + { + PtUnrealizeWidget(window); + PtDestroyWidget(window); + window=NULL; + } + + if (phevent!=NULL) + { + SDL_free(phevent); + phevent=NULL; + } +} + +static int ph_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + SDL_Rect updaterect; + + updaterect.x = updaterect.y = 0; + updaterect.w = this->screen->w; + updaterect.h = this->screen->h; + + /* palette emulation code, using palette of the PhImage_t struct */ + if (desktoppal==SDLPH_PAL_EMULATE) + { + if ((SDL_Image) && (SDL_Image->palette)) + { + for (i=firstcolor; ipalette[i] = syspalph[i]; + } + + /* image needs to be redrawn */ + this->UpdateRects(this, 1, &updaterect); + } + } + else + { + if (desktoppal==SDLPH_PAL_SYSTEM) + { + for (i=firstcolor; iscreen->flags & SDL_FULLSCREEN) != SDL_FULLSCREEN) + { + /* window mode must use soft palette */ + PgSetPalette(&syspalph[firstcolor], 0, firstcolor, ncolors, Pg_PALSET_GLOBAL, 0); + /* image needs to be redrawn */ + this->UpdateRects(this, 1, &updaterect); + } + else + { + /* fullscreen mode must use hardware palette */ + PgSetPalette(&syspalph[firstcolor], 0, firstcolor, ncolors, Pg_PALSET_GLOBAL, 0); + } + } + else + { + /* SDLPH_PAL_NONE do nothing */ + } + } + + return 1; +} + diff --git a/apps/plugins/sdl/src/video/photon/SDL_ph_video.h b/apps/plugins/sdl/src/video/photon/SDL_ph_video.h new file mode 100644 index 0000000000..3995d3505e --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_ph_video.h @@ -0,0 +1,157 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_VIDEO_H__ +#define __SDL_PH_VIDEO_H__ + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +#include + +#include +#include +#include +#include + +#if SDL_VIDEO_OPENGL + #if (_NTO_VERSION < 630) + #include + #else + #include + #include + #endif /* 6.3.0 */ +#endif /* SDL_VIDEO_OPENGL */ + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice* this + +#define PH_OGL_MAX_ATTRIBS 32 + +#define SDLPH_PAL_NONE 0x00000000L +#define SDLPH_PAL_EMULATE 0x00000001L +#define SDLPH_PAL_SYSTEM 0x00000002L + +typedef struct +{ + unsigned char* Y; + unsigned char* V; + unsigned char* U; +} FRAMEDATA; + +/* Mask values for SDL_ReallocFormat() */ +struct ColourMasks +{ + Uint32 red; + Uint32 green; + Uint32 blue; + Uint32 alpha; + Uint32 bpp; +}; + +/* Private display data */ +struct SDL_PrivateVideoData +{ + PgDisplaySettings_t mode_settings; + PtWidget_t *Window; /* used to handle input events */ + PhImage_t *image; /* used to display image */ +#if SDL_VIDEO_OPENGL + #if (_NTO_VERSION < 630) + PdOpenGLContext_t* OGLContext; /* OpenGL context */ + void* OGLBuffers; /* OpenGL buffers (unused) */ + #else + qnxglc_t* OGLContext; /* OpenGL context for the 6.3 */ + qnxgl_bufs_t* OGLBuffers; /* OpenGL buffers for the 6.3 */ + #endif /* 630 */ + + Uint32 OGLFlags; /* OpenGL flags */ + Uint32 OGLBPP; /* OpenGL bpp */ +#endif /* SDL_VIDEO_OPENGL */ + PgColor_t savedpal[_Pg_MAX_PALETTE]; + PgColor_t syspalph[_Pg_MAX_PALETTE]; + + struct + { + PdDirectContext_t* direct_context; + PdOffscreenContext_t* offscreen_context; + PdOffscreenContext_t* offscreen_backcontext; + PhDrawContext_t* oldDC; + uint8_t* dc_ptr; + unsigned char* CurrentFrameData; + unsigned char* FrameData0; + unsigned char* FrameData1; + Uint32 current; + Uint32 flags; + } ocimage; + + PgHWCaps_t graphics_card_caps; /* Graphics card caps at the moment of start */ + PgVideoModeInfo_t desktop_mode; /* Current desktop video mode information */ + int old_video_mode; /* Stored mode before fullscreen switch */ + int old_refresh_rate; /* Stored refresh rate befor fullscreen switch */ + + int mouse_relative; + WMcursor* BlankCursor; + uint32_t videomode_emulatemode; + + Uint32 visualbpp; /* current visual bpp */ + Uint32 desktopbpp; /* bpp of desktop at the moment of start */ + Uint32 desktoppal; /* palette mode emulation or system */ + + int currently_fullscreen; + int currently_hided; /* 1 - window hided (minimazed), 0 - normal */ + int currently_maximized; /* 1 - window hided (minimazed), 0 - normal */ + + PhEvent_t* event; + SDL_Overlay* overlay; +}; + +#define mode_settings (this->hidden->mode_settings) +#define window (this->hidden->Window) +#define SDL_Image (this->hidden->image) +#define OCImage (this->hidden->ocimage) +#define old_video_mode (this->hidden->old_video_mode) +#define old_refresh_rate (this->hidden->old_refresh_rate) +#define graphics_card_caps (this->hidden->graphics_card_caps) +#define desktopbpp (this->hidden->desktopbpp) +#define visualbpp (this->hidden->visualbpp) +#define desktoppal (this->hidden->desktoppal) +#define savedpal (this->hidden->savedpal) +#define syspalph (this->hidden->syspalph) +#define currently_fullscreen (this->hidden->currently_fullscreen) +#define currently_hided (this->hidden->currently_hided) +#define currently_maximized (this->hidden->currently_maximized) +#define phevent (this->hidden->event) +#define current_overlay (this->hidden->overlay) +#define desktop_mode (this->hidden->desktop_mode) +#define mouse_relative (this->hidden->mouse_relative) +#define SDL_BlankCursor (this->hidden->BlankCursor) +#define videomode_emulatemode (this->hidden->videomode_emulatemode) + +#if SDL_VIDEO_OPENGL + #define oglctx (this->hidden->OGLContext) + #define oglbuffers (this->hidden->OGLBuffers) + #define oglflags (this->hidden->OGLFlags) + #define oglbpp (this->hidden->OGLBPP) +#endif /* SDL_VIDEO_OPENGL */ + +#endif /* __SDL_PH_VIDEO_H__ */ diff --git a/apps/plugins/sdl/src/video/photon/SDL_ph_wm.c b/apps/plugins/sdl/src/video/photon/SDL_ph_wm.c new file mode 100644 index 0000000000..8e75d0b577 --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_ph_wm.c @@ -0,0 +1,118 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include +#include +#include +#include + +#include "SDL_version.h" +#include "SDL_timer.h" +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ph_modes_c.h" +#include "SDL_ph_wm_c.h" + +void ph_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask) +{ + return; +} + +/* Set window caption */ +void ph_SetCaption(_THIS, const char *title, const char *icon) +{ + SDL_Lock_EventThread(); + + /* sanity check for set caption call before window init */ + if (window!=NULL) + { + PtSetResource(window, Pt_ARG_WINDOW_TITLE, title, 0); + } + + SDL_Unlock_EventThread(); +} + +/* Iconify current window */ +int ph_IconifyWindow(_THIS) +{ + PhWindowEvent_t windowevent; + + SDL_Lock_EventThread(); + + SDL_memset(&windowevent, 0, sizeof(windowevent)); + windowevent.event_f = Ph_WM_HIDE; + windowevent.event_state = Ph_WM_EVSTATE_HIDE; + windowevent.rid = PtWidgetRid(window); + PtForwardWindowEvent(&windowevent); + + SDL_Unlock_EventThread(); + + return 0; +} + +SDL_GrabMode ph_GrabInputNoLock(_THIS, SDL_GrabMode mode) +{ + short abs_x, abs_y; + + if( mode == SDL_GRAB_OFF ) + { + PtSetResource(window, Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISALTKEY); + } + else + { + PtSetResource(window, Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISALTKEY); + + PtGetAbsPosition(window, &abs_x, &abs_y); + PhMoveCursorAbs(PhInputGroup(NULL), abs_x + SDL_VideoSurface->w/2, abs_y + SDL_VideoSurface->h/2); + } + + SDL_Unlock_EventThread(); + + return(mode); +} + +SDL_GrabMode ph_GrabInput(_THIS, SDL_GrabMode mode) +{ + SDL_Lock_EventThread(); + mode = ph_GrabInputNoLock(this, mode); + SDL_Unlock_EventThread(); + + return(mode); +} + + +int ph_GetWMInfo(_THIS, SDL_SysWMinfo *info) +{ + if (info->version.major <= SDL_MAJOR_VERSION) + { + return 1; + } + else + { + SDL_SetError("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return -1; + } +} diff --git a/apps/plugins/sdl/src/video/photon/SDL_ph_wm_c.h b/apps/plugins/sdl/src/video/photon/SDL_ph_wm_c.h new file mode 100644 index 0000000000..72bbfd217d --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_ph_wm_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_WM_H__ +#define __SDL_PH_WM_H__ + +#include "SDL_ph_video.h" + +/* Functions to be exported */ +extern void ph_SetCaption(_THIS, const char *title, const char *icon); +extern void ph_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask); +extern int ph_IconifyWindow(_THIS); +extern SDL_GrabMode ph_GrabInputNoLock(_THIS, SDL_GrabMode mode); +extern SDL_GrabMode ph_GrabInput(_THIS, SDL_GrabMode mode); +extern int ph_GetWMInfo(_THIS, SDL_SysWMinfo *info); + +#endif /* __SDL_PH_WM_H__ */ diff --git a/apps/plugins/sdl/src/video/photon/SDL_phyuv.c b/apps/plugins/sdl/src/video/photon/SDL_phyuv.c new file mode 100644 index 0000000000..06c72fded4 --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_phyuv.c @@ -0,0 +1,504 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the QNX Realtime Platform version of SDL YUV video overlays */ + +#include + +#include +#include + +#include "SDL_video.h" +#include "SDL_phyuv_c.h" +#include "../SDL_yuvfuncs.h" + +#define OVERLAY_STATE_UNINIT 0 +#define OVERLAY_STATE_ACTIVE 1 + +/* The functions are used to manipulate software video overlays */ +static struct private_yuvhwfuncs ph_yuvfuncs = +{ + ph_LockYUVOverlay, + ph_UnlockYUVOverlay, + ph_DisplayYUVOverlay, + ph_FreeYUVOverlay +}; + +int grab_ptrs2(PgVideoChannel_t* channel, FRAMEDATA* Frame0, FRAMEDATA* Frame1) +{ + int planes = 0; + + /* Buffers have moved; re-obtain the pointers */ + Frame0->Y = (unsigned char *)PdGetOffscreenContextPtr(channel->yplane1); + Frame1->Y = (unsigned char *)PdGetOffscreenContextPtr(channel->yplane2); + Frame0->U = (unsigned char *)PdGetOffscreenContextPtr(channel->vplane1); + Frame1->U = (unsigned char *)PdGetOffscreenContextPtr(channel->vplane2); + Frame0->V = (unsigned char *)PdGetOffscreenContextPtr(channel->uplane1); + Frame1->V = (unsigned char *)PdGetOffscreenContextPtr(channel->uplane2); + + if (Frame0->Y) + planes++; + + if (Frame0->U) + planes++; + + if (Frame0->V) + planes++; + + return planes; +} + +SDL_Overlay* ph_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface* display) +{ + SDL_Overlay* overlay; + struct private_yuvhwdata* hwdata; + int vidport; + int rtncode; + int planes; + int i=0; + PhPoint_t pos; + + /* Create the overlay structure */ + overlay = SDL_calloc(1, sizeof(SDL_Overlay)); + + if (overlay == NULL) + { + SDL_OutOfMemory(); + return NULL; + } + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + overlay->hwdata = NULL; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &ph_yuvfuncs; + + /* Create the pixel data and lookup tables */ + hwdata = SDL_calloc(1, sizeof(struct private_yuvhwdata)); + + if (hwdata == NULL) + { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return NULL; + } + + overlay->hwdata = hwdata; + + PhDCSetCurrent(0); + if (overlay->hwdata->channel == NULL) + { + if ((overlay->hwdata->channel = PgCreateVideoChannel(Pg_VIDEO_CHANNEL_SCALER, 0)) == NULL) + { + SDL_SetError("ph_CreateYUVOverlay(): Create channel failed: %s\n", strerror(errno)); + SDL_FreeYUVOverlay(overlay); + return NULL; + + } + } + + overlay->hwdata->forcedredraw=0; + + PtGetAbsPosition(window, &pos.x, &pos.y); + overlay->hwdata->CurrentWindowPos.x = pos.x; + overlay->hwdata->CurrentWindowPos.y = pos.y; + overlay->hwdata->CurrentViewPort.pos.x = 0; + overlay->hwdata->CurrentViewPort.pos.y = 0; + overlay->hwdata->CurrentViewPort.size.w = width; + overlay->hwdata->CurrentViewPort.size.h = height; + overlay->hwdata->State = OVERLAY_STATE_UNINIT; + overlay->hwdata->FrameData0 = (FRAMEDATA *) SDL_calloc(1, sizeof(FRAMEDATA)); + overlay->hwdata->FrameData1 = (FRAMEDATA *) SDL_calloc(1, sizeof(FRAMEDATA)); + + vidport = -1; + i=0; + + overlay->hwdata->ischromakey=0; + + do { + SDL_memset(&overlay->hwdata->caps, 0x00, sizeof(PgScalerCaps_t)); + overlay->hwdata->caps.size = sizeof(PgScalerCaps_t); + rtncode = PgGetScalerCapabilities(overlay->hwdata->channel, i, &overlay->hwdata->caps); + if (rtncode==0) + { + if (overlay->hwdata->caps.format==format) + { + if ((overlay->hwdata->caps.flags & Pg_SCALER_CAP_DST_CHROMA_KEY) == Pg_SCALER_CAP_DST_CHROMA_KEY) + { + overlay->hwdata->ischromakey=1; + } + vidport=1; + break; + } + } + else + { + break; + } + i++; + } while(1); + + + if (vidport == -1) + { + SDL_SetError("No available video ports for requested format\n"); + SDL_FreeYUVOverlay(overlay); + return NULL; + } + + overlay->hwdata->format = format; + overlay->hwdata->props.format = format; + overlay->hwdata->props.size = sizeof(PgScalerProps_t); + overlay->hwdata->props.src_dim.w = width; + overlay->hwdata->props.src_dim.h = height; + + /* overlay->hwdata->chromakey = PgGetOverlayChromaColor(); */ + overlay->hwdata->chromakey = PgRGB(12, 6, 12); /* very dark pink color */ + overlay->hwdata->props.color_key = overlay->hwdata->chromakey; + + PhAreaToRect(&overlay->hwdata->CurrentViewPort, &overlay->hwdata->props.viewport); + + overlay->hwdata->props.flags = Pg_SCALER_PROP_DOUBLE_BUFFER; + + if ((overlay->hwdata->ischromakey)&&(overlay->hwdata->chromakey)) + { + overlay->hwdata->props.flags |= Pg_SCALER_PROP_CHROMA_ENABLE; + overlay->hwdata->props.flags |= Pg_SCALER_PROP_CHROMA_SPECIFY_KEY_MASK; + } + else + { + overlay->hwdata->props.flags &= ~Pg_SCALER_PROP_CHROMA_ENABLE; + } + + rtncode = PgConfigScalerChannel(overlay->hwdata->channel, &overlay->hwdata->props); + + switch(rtncode) + { + case -1: SDL_SetError("PgConfigScalerChannel failed\n"); + SDL_FreeYUVOverlay(overlay); + return NULL; + case 1: + case 0: + default: + break; + } + + planes = grab_ptrs2(overlay->hwdata->channel, overlay->hwdata->FrameData0, overlay->hwdata->FrameData1); + + if(overlay->hwdata->channel->yplane1 != NULL) + overlay->hwdata->YStride = overlay->hwdata->channel->yplane1->pitch; + if(overlay->hwdata->channel->vplane1 != NULL) + overlay->hwdata->UStride = overlay->hwdata->channel->vplane1->pitch; + if(overlay->hwdata->channel->uplane1 != NULL) + overlay->hwdata->VStride = overlay->hwdata->channel->uplane1->pitch; + + /* check for the validness of all planes */ + if ((overlay->hwdata->channel->yplane1 == NULL) && + (overlay->hwdata->channel->uplane1 == NULL) && + (overlay->hwdata->channel->vplane1 == NULL)) + { + SDL_FreeYUVOverlay(overlay); + SDL_SetError("PgConfigScaler() returns all planes equal NULL\n"); + return NULL; + } +/* + overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel); + + if (overlay->hwdata->current==0) + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0; + } + else + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1; + } +*/ + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0; + +/* + overlay->hwdata->locked = 1; +*/ + + /* Find the pitch and offset values for the overlay */ + overlay->planes = planes; + overlay->pitches = SDL_calloc(overlay->planes, sizeof(Uint16)); + overlay->pixels = SDL_calloc(overlay->planes, sizeof(Uint8*)); + if (!overlay->pitches || !overlay->pixels) + { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + + if (overlay->planes > 0) + { + overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch; + overlay->pixels[0] = overlay->hwdata->CurrentFrameData->Y; + } + if (overlay->planes > 1) + { + overlay->pitches[1] = overlay->hwdata->channel->vplane1->pitch; + overlay->pixels[1] = overlay->hwdata->CurrentFrameData->U; + } + if (overlay->planes > 2) + { + overlay->pitches[2] = overlay->hwdata->channel->uplane1->pitch; + overlay->pixels[2] = overlay->hwdata->CurrentFrameData->V; + } + + overlay->hwdata->State = OVERLAY_STATE_ACTIVE; + overlay->hwdata->scaler_on = 0; + overlay->hw_overlay = 1; + + current_overlay=overlay; + + return overlay; +} + +int ph_LockYUVOverlay(_THIS, SDL_Overlay* overlay) +{ + if (overlay == NULL) + { + return -1; + } + + overlay->hwdata->locked = 1; + +/* overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel); + if (overlay->hwdata->current == -1) + { + SDL_SetError("ph_LockYUVOverlay: PgNextFrame() failed, bailing out\n"); + SDL_FreeYUVOverlay(overlay); + return 0; + } + + if (overlay->hwdata->current == 0) + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0; + } + else + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1; + } + + if (overlay->planes > 0) + { + overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch; + overlay->pixels[0] = overlay->hwdata->CurrentFrameData->Y; + } + if (overlay->planes > 1) + { + overlay->pitches[1] = overlay->hwdata->channel->uplane1->pitch; + overlay->pixels[1] = overlay->hwdata->CurrentFrameData->U; + } + if (overlay->planes > 2) + { + overlay->pitches[2] = overlay->hwdata->channel->vplane1->pitch; + overlay->pixels[2] = overlay->hwdata->CurrentFrameData->V; + } +*/ + + return(0); +} + +void ph_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay) +{ + if (overlay == NULL) + { + return; + } + + overlay->hwdata->locked = 0; +} + +int ph_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* src, SDL_Rect* dst) +{ + int rtncode; + PhPoint_t pos; + SDL_Rect backrect; + PhRect_t windowextent; + int winchanged=0; + + if ((overlay == NULL) || (overlay->hwdata==NULL)) + { + return -1; + } + + if (overlay->hwdata->State == OVERLAY_STATE_UNINIT) + { + return -1; + } + + PtGetAbsPosition(window, &pos.x, &pos.y); + if ((pos.x!=overlay->hwdata->CurrentWindowPos.x) || + (pos.y!=overlay->hwdata->CurrentWindowPos.y)) + { + winchanged=1; + overlay->hwdata->CurrentWindowPos.x=pos.x; + overlay->hwdata->CurrentWindowPos.y=pos.y; + } + + /* If CurrentViewPort position/size has been changed, then move/resize the viewport */ + if ((overlay->hwdata->CurrentViewPort.pos.x != dst->x) || + (overlay->hwdata->CurrentViewPort.pos.y != dst->y) || + (overlay->hwdata->CurrentViewPort.size.w != dst->w) || + (overlay->hwdata->CurrentViewPort.size.h != dst->h) || + (overlay->hwdata->scaler_on==0) || (winchanged==1) || + (overlay->hwdata->forcedredraw==1)) + { + + if (overlay->hwdata->ischromakey==1) + { + /* restore screen behind the overlay/chroma color. */ + backrect.x=overlay->hwdata->CurrentViewPort.pos.x; + backrect.y=overlay->hwdata->CurrentViewPort.pos.y; + backrect.w=overlay->hwdata->CurrentViewPort.size.w; + backrect.h=overlay->hwdata->CurrentViewPort.size.h; + this->UpdateRects(this, 1, &backrect); + + /* Draw the new rectangle of the chroma color at the viewport position */ + PgSetFillColor(overlay->hwdata->chromakey); + PgDrawIRect(dst->x, dst->y, dst->x+dst->w-1, dst->y+dst->h-1, Pg_DRAW_FILL); + PgFlush(); + } + + overlay->hwdata->props.flags |= Pg_SCALER_PROP_SCALER_ENABLE; + overlay->hwdata->scaler_on = 1; + + PhWindowQueryVisible(Ph_QUERY_CONSOLE, 0, PtWidgetRid(window), &windowextent); + overlay->hwdata->CurrentViewPort.pos.x = pos.x-windowextent.ul.x+dst->x; + overlay->hwdata->CurrentViewPort.pos.y = pos.y-windowextent.ul.y+dst->y; + overlay->hwdata->CurrentViewPort.size.w = dst->w; + overlay->hwdata->CurrentViewPort.size.h = dst->h; + PhAreaToRect(&overlay->hwdata->CurrentViewPort, &overlay->hwdata->props.viewport); + overlay->hwdata->CurrentViewPort.pos.x = dst->x; + overlay->hwdata->CurrentViewPort.pos.y = dst->y; + + rtncode = PgConfigScalerChannel(overlay->hwdata->channel, &(overlay->hwdata->props)); + + switch(rtncode) + { + case -1: + SDL_SetError("PgConfigScalerChannel() function failed\n"); + SDL_FreeYUVOverlay(overlay); + return -1; + case 1: + grab_ptrs2(overlay->hwdata->channel, overlay->hwdata->FrameData0, overlay->hwdata->FrameData1); + break; + case 0: + default: + break; + } + } + + +/* + if (overlay->hwdata->locked==0) + { + overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel); + if (overlay->hwdata->current == -1) + { + SDL_SetError("ph_LockYUVOverlay: PgNextFrame() failed, bailing out\n"); + SDL_FreeYUVOverlay(overlay); + return 0; + } + + if (overlay->hwdata->current == 0) + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0; + } + else + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1; + } + + if (overlay->planes > 0) + { + overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch; + overlay->pixels[0] = overlay->hwdata->CurrentFrameData->Y; + } + if (overlay->planes > 1) + { + overlay->pitches[1] = overlay->hwdata->channel->uplane1->pitch; + overlay->pixels[1] = overlay->hwdata->CurrentFrameData->U; + } + if (overlay->planes > 2) + { + overlay->pitches[2] = overlay->hwdata->channel->vplane1->pitch; + overlay->pixels[2] = overlay->hwdata->CurrentFrameData->V; + } + } +*/ + + return 0; +} + +void ph_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + SDL_Rect backrect; + + if (overlay == NULL) + { + return; + } + + if (overlay->hwdata == NULL) + { + return; + } + + current_overlay=NULL; + + /* restore screen behind the overlay/chroma color. */ + backrect.x=overlay->hwdata->CurrentViewPort.pos.x; + backrect.y=overlay->hwdata->CurrentViewPort.pos.y; + backrect.w=overlay->hwdata->CurrentViewPort.size.w; + backrect.h=overlay->hwdata->CurrentViewPort.size.h; + this->UpdateRects(this, 1, &backrect); + + /* it is need for some buggy drivers, that can't hide overlay before */ + /* freeing buffer, so we got trash on the srceen */ + overlay->hwdata->props.flags &= ~Pg_SCALER_PROP_SCALER_ENABLE; + PgConfigScalerChannel(overlay->hwdata->channel, &(overlay->hwdata->props)); + + overlay->hwdata->scaler_on = 0; + overlay->hwdata->State = OVERLAY_STATE_UNINIT; + + if (overlay->hwdata->channel != NULL) + { + PgDestroyVideoChannel(overlay->hwdata->channel); + overlay->hwdata->channel = NULL; + return; + } + + overlay->hwdata->CurrentFrameData = NULL; + + SDL_free(overlay->hwdata->FrameData0); + SDL_free(overlay->hwdata->FrameData1); + overlay->hwdata->FrameData0 = NULL; + overlay->hwdata->FrameData1 = NULL; + SDL_free(overlay->hwdata); +} diff --git a/apps/plugins/sdl/src/video/photon/SDL_phyuv_c.h b/apps/plugins/sdl/src/video/photon/SDL_phyuv_c.h new file mode 100644 index 0000000000..c6f73feb9f --- /dev/null +++ b/apps/plugins/sdl/src/video/photon/SDL_phyuv_c.h @@ -0,0 +1,62 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_YUV_H__ +#define __SDL_PH_YUV_H__ + +/* This is the photon implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_ph_video.h" + +struct private_yuvhwdata +{ + FRAMEDATA* CurrentFrameData; + FRAMEDATA* FrameData0; + FRAMEDATA* FrameData1; + PgScalerProps_t props; + PgScalerCaps_t caps; + PgVideoChannel_t* channel; + PhArea_t CurrentViewPort; + PhPoint_t CurrentWindowPos; + long format; + int scaler_on; + int current; + long YStride; + long VStride; + long UStride; + int ischromakey; + long chromakey; + int forcedredraw; + unsigned long State; + long flags; + int locked; +}; + +extern SDL_Overlay* ph_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface* display); +extern int ph_LockYUVOverlay(_THIS, SDL_Overlay* overlay); +extern void ph_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay); +extern int ph_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* src, SDL_Rect* dst); +extern void ph_FreeYUVOverlay(_THIS, SDL_Overlay* overlay); + +#endif /* __SDL_PH_YUV_H__ */ -- cgit v1.2.3