From a7e7b315cba2da2041a21c1348e9909e96bef45f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 7 Jun 2006 16:10:28 +0000 Subject: [PATCH] Work in progress. :) --- Makefile.in | 31 +- include/SDL_compat.h | 64 ++- include/SDL_mouse.h | 64 ++- include/SDL_video.h | 705 +++++++++++++++++++++---------- src/SDL_compat.c | 843 +++++++++++++++++++++++++++++++++++++ src/events/SDL_events_c.h | 35 +- src/events/SDL_keyboard.c | 4 +- src/events/SDL_mouse.c | 314 +++++++------- src/events/SDL_mouse_c.h | 48 +++ src/events/SDL_quit.c | 4 +- src/video/SDL_blit.c | 52 +-- src/video/SDL_bmp.c | 9 +- src/video/SDL_cursor.c | 632 +--------------------------- src/video/SDL_cursor_c.h | 43 +- src/video/SDL_pixels.c | 4 +- src/video/SDL_pixels_c.h | 2 +- src/video/SDL_surface.c | 130 +++--- src/video/SDL_sysvideo.h | 130 ++++-- src/video/SDL_video.c | 866 ++++++++++++++++++++++---------------- 19 files changed, 2369 insertions(+), 1611 deletions(-) create mode 100644 src/events/SDL_mouse_c.h diff --git a/Makefile.in b/Makefile.in index d5d854520..de5982965 100644 --- a/Makefile.in +++ b/Makefile.in @@ -125,14 +125,6 @@ uninstall-man: rm -f $(mandir)/man3/$$file; \ done -indent: - cd $(srcdir) && \ - find . \( \ - -name '*.h' -o \ - -name '*.c' -o \ - -name '*.cc' \) \ - -exec indent {} \; - clean: rm -rf $(objects) if test -f test/Makefile; then (cd test; $(MAKE) $@); fi @@ -173,6 +165,29 @@ dist $(distfile): rpm: $(distfile) rpmbuild -ta $? +# Run indent on the source to standardize coding style +indent: + @echo "Running indent... modified files:" + @cd $(srcdir) && \ + find . \( \ + -name '*.h' -o \ + -name '*.c' -o \ + -name '*.cc' \) \ + -print | \ + while read file; do \ + indent "$$file" -o "$$file.indent"; \ + if cmp "$$file" "$$file.indent" >/dev/null; then \ + rm -f "$$file.indent"; \ + else \ + echo "$$file"; \ + mv -f "$$file.indent" "$$file"; \ + fi; \ + done + +# Run indent and then commit modified files +commit: indent + svn commit + # Create a SVN snapshot that people can run update on snapshot: svn co svn://libsdl.org/trunk/SDL diff --git a/include/SDL_compat.h b/include/SDL_compat.h index 41754d166..0f296903a 100644 --- a/include/SDL_compat.h +++ b/include/SDL_compat.h @@ -36,22 +36,18 @@ extern "C" { /* *INDENT-ON* */ #endif -#define SDL_SWSURFACE 0x00000000 -#define SDL_HWSURFACE 0x00000001 -#define SDL_ASYNCBLIT 0x00000004 -#define SDL_ANYFORMAT 0x10000000 -#define SDL_HWPALETTE 0x20000000 -#define SDL_DOUBLEBUF 0x40000000 -#define SDL_FULLSCREEN 0x80000000 -#define SDL_OPENGL 0x00000002 -#define SDL_INTERNALOPENGL 0x00000008 -#define SDL_RESIZABLE 0x00000010 -#define SDL_NOFRAME 0x00000020 -#define SDL_HWACCEL 0x00000100 -#define SDL_SRCCOLORKEY 0x00001000 -#define SDL_RLEACCELOK 0x00002000 -#define SDL_RLEACCEL 0x00004000 -#define SDL_SRCALPHA 0x00010000 +#define SDL_SWSURFACE 0x00000000 +#define SDL_ANYFORMAT 0x00100000 +#define SDL_HWPALETTE 0x00200000 +#define SDL_DOUBLEBUF 0x00400000 +#define SDL_FULLSCREEN 0x00800000 +#define SDL_RESIZABLE 0x01000000 +#define SDL_NOFRAME 0x02000000 +#define SDL_OPENGL 0x04000000 +#define SDL_ASYNCBLIT 0x00000000 +#define SDL_HWACCEL 0x00000000 +#define SDL_SCREEN_SURFACE 0x10000000 /* Surface is a window screen surface */ +#define SDL_SHADOW_SURFACE 0x20000000 /* Surface is a window shadow surface */ #define SDL_APPMOUSEFOCUS 0x01 #define SDL_APPINPUTFOCUS 0x02 @@ -64,6 +60,25 @@ extern "C" { #define SDL_VIDEORESIZE SDL_EVENT_RESERVED2 #define SDL_VIDEOEXPOSE SDL_EVENT_RESERVED3 +typedef struct SDL_VideoInfo +{ + Uint32 hw_available:1; + Uint32 wm_available:1; + Uint32 UnusedBits1:6; + Uint32 UnusedBits2:1; + Uint32 blit_hw:1; + Uint32 blit_hw_CC:1; + Uint32 blit_hw_A:1; + Uint32 blit_sw:1; + Uint32 blit_sw_CC:1; + Uint32 blit_sw_A:1; + Uint32 blit_fill:1; + Uint32 UnusedBits3:16; + Uint32 video_mem; + + SDL_PixelFormat *vfmt; +} SDL_VideoInfo; + typedef enum { SDL_GRAB_QUERY = -1, @@ -71,9 +86,12 @@ typedef enum SDL_GRAB_ON = 1 } SDL_GrabMode; +#define SDL_AllocSurface SDL_CreateRGBSurface + extern DECLSPEC const SDL_version *SDLCALL SDL_Linked_Version(void); extern DECLSPEC char *SDLCALL SDL_AudioDriverName(char *namebuf, int maxlen); extern DECLSPEC char *SDLCALL SDL_VideoDriverName(char *namebuf, int maxlen); +extern DECLSPEC const SDL_VideoInfo *SDLCALL SDL_GetVideoInfo(void); extern DECLSPEC int SDLCALL SDL_VideoModeOK(int width, int height, int bpp, Uint32 flags); extern DECLSPEC SDL_Rect **SDLCALL SDL_ListModes(SDL_PixelFormat * format, @@ -81,6 +99,14 @@ extern DECLSPEC SDL_Rect **SDLCALL SDL_ListModes(SDL_PixelFormat * format, extern DECLSPEC SDL_Surface *SDLCALL SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags); extern DECLSPEC SDL_Surface *SDLCALL SDL_GetVideoSurface(void); +extern DECLSPEC void SDLCALL SDL_UpdateRects(SDL_Surface * screen, + int numrects, SDL_Rect * rects); +extern DECLSPEC void SDLCALL SDL_UpdateRect(SDL_Surface * screen, Sint32 x, + Sint32 y, Uint32 w, Uint32 h); +extern DECLSPEC int SDLCALL SDL_Flip(SDL_Surface * screen); +extern DECLSPEC SDL_Surface *SDLCALL SDL_DisplayFormat(SDL_Surface * surface); +extern DECLSPEC SDL_Surface *SDLCALL SDL_DisplayFormatAlpha(SDL_Surface * + surface); extern DECLSPEC void SDLCALL SDL_WM_SetCaption(const char *title, const char *icon); extern DECLSPEC void SDLCALL SDL_WM_GetCaption(char **title, char **icon); @@ -92,6 +118,9 @@ extern DECLSPEC Uint8 SDLCALL SDL_GetAppState(void); extern DECLSPEC int SDLCALL SDL_SetPalette(SDL_Surface * surface, int flags, SDL_Color * colors, int firstcolor, int ncolors); +extern DECLSPEC int SDLCALL SDL_SetScreenColors(SDL_Surface * screen, + SDL_Color * colors, + int firstcolor, int ncolors); extern DECLSPEC int SDLCALL SDL_GetWMInfo(SDL_SysWMinfo * info); /* Ends C function definitions when using C++ */ @@ -103,3 +132,6 @@ extern DECLSPEC int SDLCALL SDL_GetWMInfo(SDL_SysWMinfo * info); #include "close_code.h" #endif /* _SDL_compat_h */ + +/* vi: set ts=4 sw=4 expandtab: */ +extern DECLSPEC void SDLCALL SDL_WarpMouse(Uint16 x, Uint16 y); diff --git a/include/SDL_mouse.h b/include/SDL_mouse.h index aa764b584..44a285178 100644 --- a/include/SDL_mouse.h +++ b/include/SDL_mouse.h @@ -41,28 +41,53 @@ extern "C" { /* *INDENT-ON* */ #endif -typedef struct WMcursor WMcursor; /* Implementation dependent */ -typedef struct SDL_Cursor -{ - SDL_Rect area; /* The area of the mouse cursor */ - Sint16 hot_x, hot_y; /* The "tip" of the cursor */ - Uint8 *data; /* B/W cursor data */ - Uint8 *mask; /* B/W cursor mask */ - Uint8 *save[2]; /* Place to save cursor area */ - WMcursor *wm_cursor; /* Window-manager cursor */ -} SDL_Cursor; +typedef struct SDL_Cursor SDL_Cursor; /* Implementation dependent */ /* Function prototypes */ + +/* \fn int SDL_GetNumMice(void) + * + * \brief Get the number of mouse input devices available. + * + * \sa SDL_SelectMouse() + */ +extern DECLSPEC int SDLCALL SDL_GetNumMice(void); + +/* \fn int SDL_SelectMouse(int index) + * + * \brief Set the index of the currently selected mouse. + * + * \return The index of the currently selected mouse. + * + * \note You can query the currently selected mouse by passing an index of -1. + * + * \sa SDL_GetNumMice() + */ +extern DECLSPEC int SDLCALL SDL_SelectMouse(int index); + +/* \fn SDL_WindowID SDL_GetMouseFocusWindow(void) + * + * \brief Get the window which currently has focus for the currently selected mouse. + */ +extern DECLSPEC SDL_WindowID SDLCALL SDL_GetMouseFocusWindow(void); + /* - * Retrieve the current state of the mouse. + * \fn Uint8 SDL_GetMouseState(int *x, int *y) + * + * \brief Retrieve the current state of the mouse. + * * The current button state is returned as a button bitmask, which can * be tested using the SDL_BUTTON(X) macros, and x and y are set to the - * current mouse cursor position. You can pass NULL for either x or y. + * mouse cursor position relative to the focus window for the currently + * selected mouse. You can pass NULL for either x or y. */ extern DECLSPEC Uint8 SDLCALL SDL_GetMouseState(int *x, int *y); /* - * Retrieve the current state of the mouse. + * \fn Uint8 SDL_GetRelativeMouseState(int *x, int *y) + * + * \brief Retrieve the current state of the mouse. + * * The current button state is returned as a button bitmask, which can * be tested using the SDL_BUTTON(X) macros, and x and y are set to the * mouse deltas since the last call to SDL_GetRelativeMouseState(). @@ -70,9 +95,18 @@ extern DECLSPEC Uint8 SDLCALL SDL_GetMouseState(int *x, int *y); extern DECLSPEC Uint8 SDLCALL SDL_GetRelativeMouseState(int *x, int *y); /* - * Set the position of the mouse cursor (generates a mouse motion event) + * \fn void SDL_WarpMouseInWindow(SDL_WindowID windowID, int x, int y) + * + * \brief Moves the currently selected mouse to the given position within the window. + * + * \param windowID The window to move the mouse into, or 0 for the current mouse focus + * \param x The x coordinate within the window + * \param y The y coordinate within the window + * + * \note This function generates a mouse motion event */ -extern DECLSPEC void SDLCALL SDL_WarpMouse(Uint16 x, Uint16 y); +extern DECLSPEC void SDLCALL SDL_WarpMouseInWindow(SDL_WindowID windowID, + int x, int y); /* * Create a cursor using the specified data and mask (in MSB format). diff --git a/include/SDL_video.h b/include/SDL_video.h index d9227795c..6c2f520bb 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -46,111 +46,17 @@ extern "C" { #define SDL_ALPHA_OPAQUE 255 #define SDL_ALPHA_TRANSPARENT 0 -/* Useful data types */ +/** + * \struct SDL_Rect + * + * \brief A rectangle, with the origin at the upper left. + */ typedef struct SDL_Rect { Sint16 x, y; Uint16 w, h; } SDL_Rect; -/* This structure should be treated as read-only, except for 'pixels', - which, if not NULL, contains the raw pixel data for the surface. -*/ -typedef struct SDL_Surface -{ - Uint32 flags; /* Read-only */ - SDL_PixelFormat *format; /* Read-only */ - int w, h; /* Read-only */ - Uint16 pitch; /* Read-only */ - void *pixels; /* Read-write */ - int offset; /* Private */ - - /* Hardware-specific surface info */ - struct private_hwdata *hwdata; - - /* clipping information */ - SDL_Rect clip_rect; /* Read-only */ - Uint32 unused1; /* for binary compatibility */ - - /* Allow recursive locks */ - Uint32 locked; /* Private */ - - /* info for fast blit mapping to other surfaces */ - struct SDL_BlitMap *map; /* Private */ - - /* format version, bumped at every change to invalidate blit maps */ - unsigned int format_version; /* Private */ - - /* Reference count -- used when freeing surface */ - int refcount; /* Read-mostly */ -} SDL_Surface; - -/* The most common video overlay formats. - For an explanation of these pixel formats, see: - http://www.webartz.com/fourcc/indexyuv.htm - - For information on the relationship between color spaces, see: - http://www.neuro.sfc.keio.ac.jp/~aly/polygon/info/color-space-faq.html - */ -#define SDL_YV12_OVERLAY 0x32315659 /* Planar mode: Y + V + U (3 planes) */ -#define SDL_IYUV_OVERLAY 0x56555949 /* Planar mode: Y + U + V (3 planes) */ -#define SDL_YUY2_OVERLAY 0x32595559 /* Packed mode: Y0+U0+Y1+V0 (1 plane) */ -#define SDL_UYVY_OVERLAY 0x59565955 /* Packed mode: U0+Y0+V0+Y1 (1 plane) */ -#define SDL_YVYU_OVERLAY 0x55595659 /* Packed mode: Y0+V0+Y1+U0 (1 plane) */ - -/* The YUV hardware video overlay */ -typedef struct SDL_Overlay -{ - Uint32 format; /* Read-only */ - int w, h; /* Read-only */ - int planes; /* Read-only */ - Uint16 *pitches; /* Read-only */ - Uint8 **pixels; /* Read-write */ - - /* Hardware-specific surface info */ - struct private_yuvhwfuncs *hwfuncs; - struct private_yuvhwdata *hwdata; - - /* Special flags */ - Uint32 hw_overlay:1; /* Flag: This overlay hardware accelerated? */ - Uint32 UnusedBits:31; -} SDL_Overlay; - -/* Evaluates to true if the surface needs to be locked before access */ -#define SDL_MUSTLOCK(surface) \ - (surface->offset || \ - ((surface->flags & (SDL_HWSURFACE|SDL_RLEACCEL)) != 0)) - -/* typedef for private surface blitting functions */ -typedef int (*SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect, - struct SDL_Surface * dst, SDL_Rect * dstrect); - - -/** - * \struct SDL_VideoInfo - * - * \brief Useful for determining the video hardware capabilities - */ -typedef struct SDL_VideoInfo -{ - Uint32 hw_available:1; /**< Flag: Can you create hardware surfaces? */ - Uint32 wm_available:1; /**< Flag: Can you talk to a window manager? */ - Uint32 UnusedBits1:6; - Uint32 UnusedBits2:1; - Uint32 blit_hw:1; /**< Flag: Accelerated blits HW --> HW */ - Uint32 blit_hw_CC:1; /**< Flag: Accelerated blits with Colorkey */ - Uint32 blit_hw_A:1; /**< Flag: Accelerated blits with Alpha */ - Uint32 blit_sw:1; /**< Flag: Accelerated blits SW --> HW */ - Uint32 blit_sw_CC:1; /**< Flag: Accelerated blits with Colorkey */ - Uint32 blit_sw_A:1; /**< Flag: Accelerated blits with Alpha */ - Uint32 blit_fill:1; /**< Flag: Accelerated color fill */ - Uint32 UnusedBits3:16; - Uint32 video_mem; /* The total amount of video memory (in K) */ - - /* Here for backwards compatibility */ - SDL_PixelFormat *vfmt; -} SDL_VideoInfo; - /** * \struct SDL_DisplayMode * @@ -204,6 +110,8 @@ typedef Uint32 SDL_WindowID; * \enum SDL_WindowFlags * * \brief The flags on a window + * + * \sa SDL_GetWindowFlags() */ typedef enum { @@ -240,6 +148,163 @@ typedef enum SDL_WINDOWEVENT_FOCUS_LOST, /**< The window has lost keyboard focus */ } SDL_WindowEventID; +/** + * \enum SDL_RendererFlags + * + * \brief Flags used when initializing a render manager. + */ +typedef enum +{ + SDL_Renderer_PresentDiscard = 0x00000001, /**< Present leaves the contents of the backbuffer undefined */ + SDL_Renderer_PresentCopy = 0x00000002, /**< Present uses a copy from back buffer to the front buffer */ + SDL_Renderer_PresentFlip2 = 0x00000004, /**< Present uses a flip, swapping back buffer and front buffer */ + SDL_Renderer_PresentFlip3 = 0x00000008, /**< Present uses a flip, rotating between two back buffers and a front buffer */ + SDL_Renderer_PresentVSync = 0x00000010, /**< Present is synchronized with the refresh rate */ + SDL_Renderer_RenderTarget = 0x00000020, /**< The renderer can create texture render targets */ + SDL_Renderer_Accelerated = 0x00000040, /**< The renderer uses hardware acceleration */ + SDL_Renderer_Minimal = 0x00000080, /**< The renderer only supports the read/write pixel and present functions */ +} SDL_RendererFlags; + +/** + * \struct SDL_RendererInfo + * + * \brief Information on the capabilities of a render manager. + */ +typedef struct SDL_RendererInfo +{ + const char *name; /**< The name of the renderer */ + Uint32 flags; /**< Supported SDL_RendererFlags */ + Uint32 blend_modes; /**< A mask of supported blend modes */ + Uint32 scale_modes; /**< A mask of supported scale modes */ + Uint32 num_texture_formats; /**< The number of available texture formats */ + Uint32 texture_formats[32]; /**< The available texture formats */ + int max_texture_width; /**< The maximimum texture width */ + int max_texture_height; /**< The maximimum texture height */ +} SDL_RendererInfo; + +/** + * \enum SDL_TextureAccess + * + * \brief The access pattern allowed for a texture + */ +typedef enum +{ + SDL_TextureAccess_Render, /**< Unlockable video memory, rendering allowed */ + SDL_TextureAccess_Remote, /**< Unlockable video memory */ + SDL_TextureAccess_Local, /**< Lockable system memory */ +} SDL_TextureAccess; + +/** + * \enum SDL_TextureBlendMode + * + * \brief The blend mode used in SDL_RenderCopy() + */ +typedef enum +{ + SDL_TextureBlendMode_None, /**< No blending */ + SDL_TextureBlendMode_Mask, /**< dst = A ? src : dst (alpha is mask) */ + SDL_TextureBlendMode_Blend, /**< dst = (src * A) + (dst * (1-A)) */ + SDL_TextureBlendMode_Add, /**< dst = (src * A) + dst */ + SDL_TextureBlendMode_Mod, /**< dst = src * dst */ +} SDL_TextureBlendMode; + +/** + * \enum SDL_TextureScaleMode + * + * \brief The scale mode used in SDL_RenderCopy() + */ +typedef enum +{ + SDL_TextureScaleMode_None, /**< No scaling, rectangles must match dimensions */ + SDL_TextureScaleMode_Fast, /**< Point sampling or equivalent algorithm */ + SDL_TextureScaleMode_Slow, /**< Linear filtering or equivalent algorithm */ + SDL_TextureScaleMode_Best, /**< Bicubic filtering or equivalent algorithm */ +} SDL_TextureScaleMode; + +/** + * \typedef SDL_TextureID + * + * \brief An efficient driver-specific representation of pixel data + */ +typedef Uint32 SDL_TextureID; + + +/* These are the currently supported flags for the SDL_surface */ +/* Used internally (read-only) */ +#define SDL_HWSURFACE 0x00000001 /* Surface represents a texture */ +#define SDL_PREALLOC 0x00000002 /* Surface uses preallocated memory */ +#define SDL_SRCALPHA 0x00000004 /* Blit uses source alpha blending */ +#define SDL_SRCCOLORKEY 0x00000008 /* Blit uses a source color key */ +#define SDL_RLEACCELOK 0x00000010 /* Private flag */ +#define SDL_RLEACCEL 0x00000020 /* Surface is RLE encoded */ + +/* Evaluates to true if the surface needs to be locked before access */ +#define SDL_MUSTLOCK(S) (((S)->flags & (SDL_HWSURFACE|SDL_RLEACCEL)) != 0) + +/* This structure should be treated as read-only, except for 'pixels', + which, if not NULL, contains the raw pixel data for the surface. +*/ +typedef struct SDL_Surface +{ + Uint32 flags; /* Read-only */ + SDL_PixelFormat *format; /* Read-only */ + int w, h; /* Read-only */ + int pitch; /* Read-only */ + void *pixels; /* Read-write */ + + /* information needed for surfaces requiring locks */ + int locked; + void *lock_data; + + /* clipping information */ + SDL_Rect clip_rect; /* Read-only */ + + /* info for fast blit mapping to other surfaces */ + struct SDL_BlitMap *map; /* Private */ + + /* format version, bumped at every change to invalidate blit maps */ + unsigned int format_version; /* Private */ + + /* Reference count -- used when freeing surface */ + int refcount; /* Read-mostly */ +} SDL_Surface; + +/* typedef for private surface blitting functions */ +typedef int (*SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect, + struct SDL_Surface * dst, SDL_Rect * dstrect); + + +/* The most common video overlay formats. + For an explanation of these pixel formats, see: + http://www.webartz.com/fourcc/indexyuv.htm + + For information on the relationship between color spaces, see: + http://www.neuro.sfc.keio.ac.jp/~aly/polygon/info/color-space-faq.html + */ +#define SDL_YV12_OVERLAY 0x32315659 /* Planar mode: Y + V + U (3 planes) */ +#define SDL_IYUV_OVERLAY 0x56555949 /* Planar mode: Y + U + V (3 planes) */ +#define SDL_YUY2_OVERLAY 0x32595559 /* Packed mode: Y0+U0+Y1+V0 (1 plane) */ +#define SDL_UYVY_OVERLAY 0x59565955 /* Packed mode: U0+Y0+V0+Y1 (1 plane) */ +#define SDL_YVYU_OVERLAY 0x55595659 /* Packed mode: Y0+V0+Y1+U0 (1 plane) */ + +/* The YUV hardware video overlay */ +typedef struct SDL_Overlay +{ + Uint32 format; /* Read-only */ + int w, h; /* Read-only */ + int planes; /* Read-only */ + Uint16 *pitches; /* Read-only */ + Uint8 **pixels; /* Read-write */ + + /* Hardware-specific surface info */ + struct private_yuvhwfuncs *hwfuncs; + struct private_yuvhwdata *hwdata; + + /* Special flags */ + Uint32 hw_overlay:1; /* Flag: This overlay hardware accelerated? */ + Uint32 UnusedBits:31; +} SDL_Overlay; + /** * \enum SDL_GLattr * @@ -266,22 +331,6 @@ typedef enum SDL_GL_SWAP_CONTROL } SDL_GLattr; -/* These are the currently supported flags for the SDL_surface */ -#define SDL_SWSURFACE 0x00000000 /* Surface is in system memory */ -#define SDL_HWSURFACE 0x00000001 /* Surface is in video memory */ -/* Available for SDL_CreateWindowSurface() */ -#define SDL_ANYFORMAT 0x10000000 /* Allow any video depth/pixel-format */ -#define SDL_HWPALETTE 0x20000000 /* Surface has exclusive palette */ -#define SDL_DOUBLEBUF 0x40000000 /* Set up double-buffered surface */ -/* Used internally (read-only) */ -#define SDL_HWACCEL 0x00000100 /* Blit uses hardware acceleration */ -#define SDL_SRCCOLORKEY 0x00001000 /* Blit uses a source color key */ -#define SDL_RLEACCELOK 0x00002000 /* Private flag */ -#define SDL_RLEACCEL 0x00004000 /* Surface is RLE encoded */ -#define SDL_SRCALPHA 0x00010000 /* Blit uses source alpha blending */ -#define SDL_PREALLOC 0x00100000 /* Surface uses preallocated memory */ -#define SDL_SCREEN_SURFACE 0x01000000 /* Surface is a window screen surface */ -#define SDL_SHADOW_SURFACE 0x02000000 /* Surface is a window shadow surface */ /* Function prototypes */ @@ -349,16 +398,6 @@ extern DECLSPEC void SDLCALL SDL_VideoQuit(void); */ extern DECLSPEC const char *SDLCALL SDL_GetCurrentVideoDriver(void); -/** - * \fn const SDL_VideoInfo *SDL_GetVideoInfo(void) - * - * \brief Returns information about the currently initialized video driver. - * - * \return A read-only pointer to information about the video hardware, - * or NULL if no video driver has been initialized. - */ -extern DECLSPEC const SDL_VideoInfo *SDLCALL SDL_GetVideoInfo(void); - /** * \fn int SDL_GetNumVideoDisplays(void) * @@ -373,6 +412,8 @@ extern DECLSPEC int SDLCALL SDL_GetNumVideoDisplays(void); * * \brief Set the index of the currently selected display. * + * \return The index of the currently selected display. + * * \note You can query the currently selected display by passing an index of -1. * * \sa SDL_GetNumVideoDisplays() @@ -451,6 +492,16 @@ extern DECLSPEC SDL_DisplayMode *SDLCALL SDL_GetClosestDisplayMode(const */ extern DECLSPEC int SDLCALL SDL_SetDisplayMode(const SDL_DisplayMode * mode); +/** + * \fn int SDL_SetDisplayColormap(SDL_Color *colors, int firstcolor, int ncolors) + * + * \brief Set the colormap for indexed display modes. + * + * \return 0 on success, or -1 if not all the colors could be set. + */ +extern DECLSPEC int SDLCALL SDL_SetDisplayColors(SDL_Color * colors, + int firstcolor, int ncolors); + /** * \fn SDL_WindowID SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) * @@ -673,37 +724,294 @@ extern DECLSPEC int SDLCALL SDL_GetWindowGrab(SDL_WindowID windowID); extern DECLSPEC void SDLCALL SDL_DestroyWindow(SDL_WindowID windowID); /** - * \fn SDL_Surface *SDL_CreateWindowSurface (SDL_WindowID windowID, Uint32 format, Uint32 flags) + * \fn int SDL_GetNumRenderers(void) * - * \brief Create an SDL_Surface representing the drawing area of the window. + * \brief Get the number of render managers on the current display. + * + * A render manager is a set of code that handles rendering and texture + * management on a particular display. Normally there is only one, but + * some drivers may have several available with different capabilities. + * + * \sa SDL_GetRendererInfo() + * \sa SDL_CreateRenderer() */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateWindowSurface(SDL_WindowID - windowID, - Uint32 format, - Uint32 flags); +extern DECLSPEC int SDLCALL SDL_GetNumRenderers(void); -/* - * Makes sure the given list of rectangles is updated on the given screen. - * If 'x', 'y', 'w' and 'h' are all 0, SDL_UpdateRect will update the entire - * screen. - * These functions should not be called while 'screen' is locked. +/** + * \fn SDL_RendererInfo *SDL_GetRendererInfo(int index) + * + * \brief Get information about a specific render manager on the current + * display. + * + * \sa SDL_CreateRenderer() */ -extern DECLSPEC void SDLCALL SDL_UpdateRects - (SDL_Surface * screen, int numrects, SDL_Rect * rects); -extern DECLSPEC void SDLCALL SDL_UpdateRect - (SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h); +extern DECLSPEC int SDLCALL SDL_GetRendererInfo(int index, + SDL_RendererInfo * info); -/* - * On hardware that supports double-buffering, this function sets up a flip - * and returns. The hardware will wait for vertical retrace, and then swap - * video buffers before the next video surface blit or lock will return. - * On hardware that doesn not support double-buffering, this is equivalent - * to calling SDL_UpdateRect(screen, 0, 0, 0, 0); - * The SDL_DOUBLEBUF flag must have been passed to SDL_SetVideoMode() when - * setting the video mode for this function to perform hardware flipping. - * This function returns 0 if successful, or -1 if there was an error. +/** + * \fn int SDL_CreateRenderer(SDL_WindowID window, int index, Uint32 flags) + * + * \brief Create and make active a 2D rendering context for a window. + * + * \param windowID The window used for rendering. + * \param index The index of the render manager to initialize, or -1 to initialize the first one supporting the requested flags. + * \param flags SDL_RendererFlags + * + * \return 0 on success, -1 if the flags were not supported, or -2 if + * there isn't enough memory to support the requested flags + * + * \sa SDL_SelectRenderer() + * \sa SDL_DestroyRenderer() */ -extern DECLSPEC int SDLCALL SDL_Flip(SDL_Surface * screen); +extern DECLSPEC int SDLCALL SDL_CreateRenderer(SDL_WindowID windowID, + int index, Uint32 flags); + +/** + * \fn int SDL_SelectRenderer(SDL_WindowID windowID) + * + * \brief Select the rendering context for a particular window. + * + * \return 0 on success, -1 if the selected window doesn't have a + * rendering context. + */ +extern DECLSPEC int SDLCALL SDL_SelectRenderer(SDL_WindowID windowID); + +/** + * \fn SDL_TextureID SDL_CreateTexture(Uint32 format, int access, int w, int h) + * + * \brief Create a texture + * + * \param format The format of the texture + * \param access One of the enumerated values in SDL_TextureAccess + * \param w The width of the texture in pixels + * \param h The height of the texture in pixels + * + * \return The created texture is returned, or 0 if no render manager was active, the format was unsupported, or the width or height were out of range. + * + * \sa SDL_QueryTexture() + * \sa SDL_DestroyTexture() + */ +extern DECLSPEC SDL_TextureID SDLCALL SDL_CreateTexture(Uint32 format, + int access, int w, + int h); + +/** + * \fn SDL_TextureID SDL_CreateTextureFromSurface(Uint32 format, int access, SDL_Surface *surface) + * + * \brief Create a texture from an existing surface + * + * \param format The format of the texture, or 0 to pick an appropriate format + * \param access One of the enumerated values in SDL_TextureAccess + * \param surface The surface containing pixel data used to fill the texture + * + * \return The created texture is returned, or 0 if no render manager was active, the format was unsupported, or the surface width or height were out of range. + * + * \note The surface is not modified or freed by this function. + * + * \sa SDL_QueryTexture() + * \sa SDL_DestroyTexture() + */ +extern DECLSPEC SDL_TextureID SDLCALL SDL_CreateTextureFromSurface(Uint32 + format, + int access, + SDL_Surface + * surface); + +/** + * \fn int SDL_QueryTexture(SDL_TextureID textureID, Uint32 *format, int *access, int *w, int *h) + * + * \brief Query the attributes of a texture + * + * \param texture A texture to be queried + * \param format A pointer filled in with the raw format of the texture. The actual format may differ, but pixel transfers will use this format. + * \param access A pointer filled in with the actual access to the texture. + * \param w A pointer filled in with the width of the texture in pixels + * \param h A pointer filled in with the height of the texture in pixels + * + * \return 0 on success, or -1 if the texture is not valid + */ +extern DECLSPEC int SDLCALL SDL_QueryTexture(SDL_TextureID textureID, + Uint32 * format, int *access, + int *w, int *h); + +/** + * \fn int SDL_SetTexturePalette(SDL_TextureID textureID, SDL_Color * colors, int firstcolor, int ncolors) + * + * \brief Update an indexed texture with a color palette + * + * \param texture The texture to update + * \param colors The array of RGB color data + * \param firstcolor The first index to update + * \param ncolors The number of palette entries to fill with the color data + * + * \return 0 on success, or -1 if the texture is not valid or not an indexed texture + */ +extern DECLSPEC int SDLCALL SDL_SetTexturePalette(SDL_TextureID textureID, + SDL_Color * colors, + int firstcolor, + int ncolors); + +/** + * \fn int SDL_UpdateTexture(SDL_TextureID textureID, SDL_Rect *rect, const void *pixels, int pitch) + * + * \brief Update the given texture rectangle with new pixel data. + * + * \param texture The texture to update + * \param rect A pointer to the rectangle of pixels to update, or NULL to update the entire texture. + * \param pixels The raw pixel data + * \param pitch The number of bytes between rows of pixel data + * + * \return 0 on success, or -1 if the texture is not valid + * + * \note This is a very slow function for textures not created with SDL_TextureAccess_Local. + */ +extern DECLSPEC int SDLCALL SDL_UpdateTexture(SDL_TextureID textureID, + SDL_Rect * rect, + const void *pixels, int pitch); + +/** + * \fn void SDL_LockTexture(SDL_TextureID textureID, SDL_Rect *rect, int markDirty, void **pixels, int *pitch) + * + * \brief Lock a portion of the texture for pixel access. + * + * \param texture The texture to lock for access, which must have been created with SDL_TextureAccess_Local. + * \param rect A pointer to the rectangle to lock for access. If the rect is NULL, the entire texture will be locked. + * \param markDirty If this is nonzero, the locked area will be marked dirty when the texture is unlocked. + * \param pixels This is filled in with a pointer to the locked pixels, appropriately offset by the locked area. + * \param pitch This is filled in with the pitch of the locked pixels. + * + * \return 0 on success, or -1 if the texture is not valid or was created with SDL_TextureAccess_Remote + * + * \sa SDL_DirtyTexture() + * \sa SDL_UnlockTexture() + */ +extern DECLSPEC int SDLCALL SDL_LockTexture(SDL_TextureID textureID, + SDL_Rect * rect, int markDirty, + void **pixels, int *pitch); + +/** + * \fn void SDL_UnlockTexture(SDL_TextureID textureID) + * + * \brief Unlock a texture, uploading the changes to video memory, if needed. + * + * \sa SDL_LockTexture() + * \sa SDL_DirtyTexture() + */ +extern DECLSPEC void SDLCALL SDL_UnlockTexture(SDL_TextureID textureID); + +/** + * \fn void SDL_DirtyTexture(SDL_TextureID textureID, int numrects, SDL_Rect * rects) + * + * \brief Mark the specified rectangles of the texture as dirty. + * + * \note The texture must have been created with SDL_TextureAccess_Local. + * + * \sa SDL_LockTexture() + * \sa SDL_UnlockTexture() + */ +extern DECLSPEC void SDLCALL SDL_DirtyTexture(SDL_TextureID textureID, + int numrects, SDL_Rect * rects); + +/** + * \fn void SDL_SelectRenderTexture(SDL_TextureID textureID) + * + * \brief Select a texture as the rendering target, or 0 to reselect the current window. + * + * \note The texture must have been created with SDL_TextureAccess_Render. + */ +extern DECLSPEC void SDLCALL SDL_SelectRenderTexture(SDL_TextureID textureID); + +/** + * \fn void SDL_RenderFill(SDL_Rect *rect, Uint32 color) + * + * \brief Fill the current rendering target with the specified color. + * + * \param rect A pointer to the destination rectangle, or NULL for the entire rendering target. + * \param color An ARGB color value. + * + * \return 0 on success, or -1 if there is no renderer current + */ +extern DECLSPEC int SDLCALL SDL_RenderFill(SDL_Rect * rect, Uint32 color); + +/** + * \fn int SDL_RenderCopy(SDL_TextureID textureID, SDL_Rect *srcrect, SDL_Rect *dstrect, Uint32 blendMode, Uint32 scaleMode) + * + * \brief Copy a portion of the texture to the current rendering target. + * + * \param texture The source texture. + * \param srcrect A pointer to the source rectangle, or NULL for the entire texture. + * \param dstrect A pointer to the destination rectangle, or NULL for the entire rendering target. + * \param blendMode SDL_TextureBlendMode to be used if the source texture has an alpha channel. + * \param scaleMode SDL_TextureScaleMode to be used if the source and destination rectangles don't have the same width and height. + * + * \return 0 on success, or -1 if there is no renderer current, or the driver doesn't support the requested operation. + * + * \note You can check the video driver info to see what operations are supported. + */ +extern DECLSPEC int SDLCALL SDL_RenderCopy(SDL_TextureID textureID, + SDL_Rect * srcrect, + SDL_Rect * dstrect, int blendMode, + int scaleMode); + +/** + * \fn int SDL_RenderReadPixels(SDL_Rect *rect, void *pixels, int pitch) + * + * \brief Read pixels from the current rendering target. + * + * \param rect A pointer to the rectangle to read, or NULL for the entire render target + * \param pixels A pointer to be filled in with the pixel data + * \param pitch The pitch of the pixels parameter + * + * \return 0 on success, or -1 if pixel reading is not supported. + * + * \warning This is a very slow operation, and should not be used frequently. + */ +extern DECLSPEC int SDLCALL SDL_RenderReadPixels(SDL_Rect * rect, + void *pixels, int pitch); + +/** + * \fn int SDL_RenderWritePixels(SDL_Rect *rect, const void *pixels, int pitch) + * + * \brief Write pixels to the current rendering target. + * + * \param rect A pointer to the rectangle to write, or NULL for the entire render target + * \param pixels A pointer to the pixel data to write + * \param pitch The pitch of the pixels parameter + * + * \return 0 on success, or -1 if pixel writing is not supported. + * + * \warning This is a very slow operation, and should not be used frequently. + */ +extern DECLSPEC int SDLCALL SDL_RenderWritePixels(SDL_Rect * rect, + const void *pixels, + int pitch); + +/** + * \fn void SDL_RenderPresent(void) + * + * \brief Update the screen with rendering performed. + */ +extern DECLSPEC void SDLCALL SDL_RenderPresent(void); + +/** + * \fn void SDL_DestroyTexture(SDL_TextureID textureID); + * + * \brief Destroy the specified texture. + * + * \sa SDL_CreateTexture() + * \sa SDL_CreateTextureFromSurface() + */ +extern DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_TextureID textureID); + +/** + * \fn void SDL_DestroyRenderer(SDL_WindowID windowID); + * + * \brief Destroy the rendering context for a window and free associated + * textures. + * + * \sa SDL_CreateRenderer() + */ +extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_WindowID windowID); /* * Set the gamma correction for each of the color channels. @@ -796,33 +1104,9 @@ extern DECLSPEC void SDLCALL SDL_GetRGBA(Uint32 pixel, SDL_PixelFormat * fmt, * If the function runs out of memory, it will return NULL. * * The 'flags' tell what kind of surface to create. - * SDL_SWSURFACE means that the surface should be created in system memory. - * SDL_HWSURFACE means that the surface should be created in video memory, - * with the same format as the display surface. This is useful for surfaces - * that will not change much, to take advantage of hardware acceleration - * when being blitted to the display surface. - * SDL_ASYNCBLIT means that SDL will try to perform asynchronous blits with - * this surface, but you must always lock it before accessing the pixels. - * SDL will wait for current blits to finish before returning from the lock. * SDL_SRCCOLORKEY indicates that the surface will be used for colorkey blits. - * If the hardware supports acceleration of colorkey blits between - * two surfaces in video memory, SDL will try to place the surface in - * video memory. If this isn't possible or if there is no hardware - * acceleration available, the surface will be placed in system memory. - * SDL_SRCALPHA means that the surface will be used for alpha blits and - * if the hardware supports hardware acceleration of alpha blits between - * two surfaces in video memory, to place the surface in video memory - * if possible, otherwise it will be placed in system memory. - * If the surface is created in video memory, blits will be _much_ faster, - * but the surface format must be identical to the video surface format, - * and the only way to access the pixels member of the surface is to use - * the SDL_LockSurface() and SDL_UnlockSurface() calls. - * If the requested surface actually resides in video memory, SDL_HWSURFACE - * will be set in the flags member of the returned surface. If for some - * reason the surface could not be placed in video memory, it will not have - * the SDL_HWSURFACE flag set, and will be created in system memory instead. - */ -#define SDL_AllocSurface SDL_CreateRGBSurface + * SDL_SRCALPHA means that the surface will be used for alpha blits. + */ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurface (Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); @@ -835,6 +1119,8 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); +extern DECLSPEC SDL_Surface *SDLCALL +SDL_CreateRGBSurfaceFromTexture(SDL_TextureID textureID); extern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface * surface); /* @@ -846,9 +1132,7 @@ extern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface * surface); * * Not all surfaces require locking. If SDL_MUSTLOCK(surface) evaluates * to 0, then you can read and write to the surface at any time, and the - * pixel format of the surface will not change. In particular, if the - * SDL_HWSURFACE flag is not given when calling SDL_SetVideoMode(), you - * will not need to lock the display surface before accessing it. + * pixel format of the surface will not change. * * No operating system or library calls should be made between lock/unlock * pairs, as critical system locks may be held during this time. @@ -950,6 +1234,18 @@ extern DECLSPEC void SDLCALL SDL_GetClipRect(SDL_Surface * surface, extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurface (SDL_Surface * src, SDL_PixelFormat * fmt, Uint32 flags); +/* + * This function performs a fast fill of the given rectangle with 'color' + * The given rectangle is clipped to the destination surface clip area + * and the final fill rectangle is saved in the passed in pointer. + * If 'dstrect' is NULL, the whole surface will be filled with 'color' + * The color should be a pixel of the format used by the surface, and + * can be generated by the SDL_MapRGB() function. + * This function returns 0 on success, or -1 on error. + */ +extern DECLSPEC int SDLCALL SDL_FillRect + (SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color); + /* * This performs a fast blit from the source surface to the destination * surface. It assumes that the source and destination rectangles are @@ -1034,45 +1330,16 @@ extern DECLSPEC int SDLCALL SDL_LowerBlit (SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect); -/* - * This function performs a fast fill of the given rectangle with 'color' - * The given rectangle is clipped to the destination surface clip area - * and the final fill rectangle is saved in the passed in pointer. - * If 'dstrect' is NULL, the whole surface will be filled with 'color' - * The color should be a pixel of the format used by the surface, and - * can be generated by the SDL_MapRGB() function. - * This function returns 0 on success, or -1 on error. - */ -extern DECLSPEC int SDLCALL SDL_FillRect - (SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color); - -/* - * This function takes a surface and copies it to a new surface of the - * pixel format and colors of the video framebuffer, suitable for fast - * blitting onto the display surface. It calls SDL_ConvertSurface() - * - * If you want to take advantage of hardware colorkey or alpha blit - * acceleration, you should set the colorkey and alpha value before - * calling this function. - * - * If the conversion fails or runs out of memory, it returns NULL - */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_DisplayFormat(SDL_Surface * surface); - -/* - * This function takes a surface and copies it to a new surface of the - * pixel format and colors of the video framebuffer (if possible), - * suitable for fast alpha blitting onto the display surface. - * The new surface will always have an alpha channel. - * - * If you want to take advantage of hardware colorkey or alpha blit - * acceleration, you should set the colorkey and alpha value before - * calling this function. +/** + * \fn int SDL_SoftStretch(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) * - * If the conversion fails or runs out of memory, it returns NULL + * \brief Perform a fast, low quality, stretch blit between two surfaces of the same pixel format. + * \note This function uses a static buffer, and is not thread-safe. */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_DisplayFormatAlpha(SDL_Surface * - surface); +extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface * src, + SDL_Rect * srcrect, + SDL_Surface * dst, + SDL_Rect * dstrect); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -1145,12 +1412,6 @@ extern DECLSPEC int SDLCALL SDL_GL_GetAttribute(SDL_GLattr attr, int *value); */ extern DECLSPEC void SDLCALL SDL_GL_SwapBuffers(void); -/* Not in public API at the moment - do not use! */ -extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface * src, - SDL_Rect * srcrect, - SDL_Surface * dst, - SDL_Rect * dstrect); - /* Ends C function definitions when using C++ */ #ifdef __cplusplus /* *INDENT-OFF* */ diff --git a/src/SDL_compat.c b/src/SDL_compat.c index 1dea0beab..ef0b7345b 100644 --- a/src/SDL_compat.c +++ b/src/SDL_compat.c @@ -53,6 +53,23 @@ SDL_VideoDriverName(char *namebuf, int maxlen) return NULL; } +const SDL_VideoInfo * +SDL_GetVideoInfo(void) +{ + static SDL_VideoInfo info; + + /* Memory leak, compatibility code, who cares? */ + if (!info.vfmt && SDL_GetDesktopDisplayMode()) { + int bpp; + Uint32 Rmask, Gmask, Bmask, Amask; + + SDL_PixelFormatEnumToMasks(SDL_GetDesktopDisplayMode()->format, &bpp, + &Rmask, &Gmask, &Bmask, &Amask); + info.vfmt = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); + } + return &info; +} + int SDL_VideoModeOK(int width, int height, int bpp, Uint32 flags) { @@ -295,6 +312,91 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) return SDL_CreateWindowSurface(window, desired_format, flags); } +SDL_Surface * +SDL_CreateWindowSurface(SDL_WindowID windowID, Uint32 format, Uint32 flags) +{ + SDL_Window *window = SDL_GetWindowFromID(windowID); + Uint32 black; + SDL_Surface *surface; + + if (!window) { + return NULL; + } + + if (!_this->CreateWindowSurface) { + return NULL; + } + + if (!window->surface) { + _this->CreateWindowSurface(_this, window, flags); + if (!window->surface) { + return NULL; + } + window->surface->flags |= SDL_SCREEN_SURFACE; + + /* If we have a palettized surface, create a default palette */ + if (window->surface->format->palette) { + SDL_Color colors[256]; + SDL_PixelFormat *vf = window->surface->format; + SDL_DitherColors(colors, vf->BitsPerPixel); + SDL_SetColors(window->surface, colors, 0, vf->palette->ncolors); + } + } + surface = window->surface; + + if (window->shadow) { + SDL_FreeSurface(window->shadow); + window->shadow = NULL; + } + + /* Create a shadow surface if necessary */ + if ((!(flags & SDL_ANYFORMAT) + && (format != SDL_GetCurrentDisplayMode()->format)) + || ((flags & SDL_HWPALETTE) + && !(window->surface->flags & SDL_HWPALETTE))) { + int bpp; + Uint32 Rmask, Gmask, Bmask, Amask; + + SDL_PixelFormatEnumToMasks(format, &bpp, &Amask, &Gmask, &Bmask, + &Amask); + window->shadow = + SDL_CreateRGBSurface(SDL_SWSURFACE, surface->w, surface->h, bpp, + Rmask, Gmask, Bmask, Amask); + if (window->shadow == NULL) { + return NULL; + } + window->shadow->flags |= SDL_SHADOW_SURFACE; + + surface = window->shadow; + + /* 8-bit shadow surfaces report that they have exclusive palette */ + if (surface->format->palette) { + surface->flags |= SDL_HWPALETTE; + if (format == SDL_GetCurrentDisplayMode()->format) { + SDL_memcpy(surface->format->palette->colors, + window->surface->format->palette->colors, + window->surface->format->palette->ncolors * + sizeof(SDL_Color)); + } else { + SDL_DitherColors(surface->format->palette->colors, bpp); + } + } + } + + /* Clear the surface for display */ + { + Uint32 black = SDL_MapRGB(surface->format, 0, 0, 0); + SDL_FillRect(surface, NULL, black); + if (surface->flags & SDL_DOUBLEBUF) { + SDL_Flip(surface); + SDL_FillRect(surface, NULL, black); + } + SDL_Flip(surface); + } + + return surface; +} + SDL_Surface * SDL_GetVideoSurface(void) { @@ -303,6 +405,201 @@ SDL_GetVideoSurface(void) return SDL_VideoSurface; } +SDL_Surface * +SDL_DisplayFormat(SDL_Surface * surface) +{ + Uint32 flags; + + if (!SDL_PublicSurface) { + SDL_SetError("No video mode has been set"); + return (NULL); + } + /* Set the flags appropriate for copying to display surface */ + if (((SDL_PublicSurface->flags & SDL_HWSURFACE) == SDL_HWSURFACE) + && _this->info.blit_hw) + flags = SDL_HWSURFACE; + else + flags = SDL_SWSURFACE; +#ifdef AUTORLE_DISPLAYFORMAT + flags |= (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA)); + flags |= SDL_RLEACCELOK; +#else + flags |= + surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA | SDL_RLEACCELOK); +#endif + return (SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags)); +} + +SDL_Surface * +SDL_DisplayFormatAlpha(SDL_Surface * surface) +{ + SDL_PixelFormat *vf; + SDL_PixelFormat *format; + SDL_Surface *converted; + Uint32 flags; + /* default to ARGB8888 */ + Uint32 amask = 0xff000000; + Uint32 rmask = 0x00ff0000; + Uint32 gmask = 0x0000ff00; + Uint32 bmask = 0x000000ff; + + if (!SDL_PublicSurface) { + SDL_SetError("No video mode has been set"); + return (NULL); + } + vf = SDL_PublicSurface->format; + + switch (vf->BytesPerPixel) { + case 2: + /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}. + For anything else (like ARGB4444) it doesn't matter + since we have no special code for it anyway */ + if ((vf->Rmask == 0x1f) && + (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) { + rmask = 0xff; + bmask = 0xff0000; + } + break; + + case 3: + case 4: + /* Keep the video format, as long as the high 8 bits are + unused or alpha */ + if ((vf->Rmask == 0xff) && (vf->Bmask == 0xff0000)) { + rmask = 0xff; + bmask = 0xff0000; + } + break; + + default: + /* We have no other optimised formats right now. When/if a new + optimised alpha format is written, add the converter here */ + break; + } + format = SDL_AllocFormat(32, rmask, gmask, bmask, amask); + flags = SDL_PublicSurface->flags & SDL_HWSURFACE; + flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK); + converted = SDL_ConvertSurface(surface, format, flags); + SDL_FreeFormat(format); + return (converted); +} + +void +SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h) +{ + if (screen) { + SDL_Rect rect; + + /* Perform some checking */ + if (w == 0) + w = screen->w; + if (h == 0) + h = screen->h; + if ((int) (x + w) > screen->w) + return; + if ((int) (y + h) > screen->h) + return; + + /* Fill the rectangle */ + rect.x = (Sint16) x; + rect.y = (Sint16) y; + rect.w = (Uint16) w; + rect.h = (Uint16) h; + SDL_UpdateRects(screen, 1, &rect); + } +} +void +SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects) +{ + int i; + SDL_Window *window; + + /* Find the window corresponding to this surface */ + window = SDL_GetWindowFromSurface(screen); + if (!window) { + SDL_SetError("Couldn't find window associated with surface"); + return; + } + + if (screen->flags & SDL_SHADOW_SURFACE) { + if (SHOULD_DRAWCURSOR(SDL_cursorstate)) { + SDL_LockCursor(); + SDL_DrawCursor(screen); + for (i = 0; i < numrects; ++i) { + SDL_LowerBlit(screen, &rects[i], window->surface, &rects[i]); + } + SDL_EraseCursor(screen); + SDL_UnlockCursor(); + } else { + for (i = 0; i < numrects; ++i) { + SDL_LowerBlit(screen, &rects[i], window->surface, &rects[i]); + } + } + + /* Fall through to video surface update */ + screen = window->surface; + } + if ((screen->flags & SDL_SCREEN_SURFACE) && _this->UpdateWindowSurface) { + /* Update the video surface */ + if (screen->offset) { + int offset_y = screen->offset / screen->pitch; + int offset_x = screen->offset % screen->pitch; + for (i = 0; i < numrects; ++i) { + rects[i].x += offset_x; + rects[i].y += offset_y; + } + _this->UpdateWindowSurface(_this, window, numrects, rects); + for (i = 0; i < numrects; ++i) { + rects[i].x -= offset_x; + rects[i].y -= offset_y; + } + } else { + _this->UpdateWindowSurface(_this, window, numrects, rects); + } + } +} + +int +SDL_Flip(SDL_Surface * screen) +{ + SDL_Window *window; + + /* Find the window corresponding to this surface */ + window = SDL_GetWindowFromSurface(screen); + if (!window) { + SDL_SetError("Couldn't find window associated with surface"); + return; + } + + /* Copy the shadow surface to the video surface */ + if (screen->flags & SDL_SHADOW_SURFACE) { + SDL_Rect rect; + + rect.x = 0; + rect.y = 0; + rect.w = screen->w; + rect.h = screen->h; + if (SHOULD_DRAWCURSOR(SDL_cursorstate)) { + SDL_LockCursor(); + SDL_DrawCursor(screen); + SDL_LowerBlit(screen, &rect, window->surface, &rect); + SDL_EraseCursor(screen); + SDL_UnlockCursor(); + } else { + SDL_LowerBlit(screen, &rect, window->surface, &rect); + } + + /* Fall through to video surface update */ + screen = window->surface; + } + if (screen->flags & SDL_DOUBLEBUF) { + _this->FlipWindowSurface(_this, window); + } else { + SDL_UpdateRect(screen, 0, 0, 0, 0); + } + return (0); +} + void SDL_WM_SetCaption(const char *title, const char *icon) { @@ -386,10 +683,556 @@ SDL_SetPalette(SDL_Surface * surface, int flags, SDL_Color * colors, SDL_SetColors(surface, colors, firstcolor, ncolors); } +int +SDL_SetScreenColors(SDL_Surface * screen, SDL_Color * colors, int firstcolor, + int ncolors) +{ + SDL_Window *window = NULL; + SDL_Palette *pal; + int gotall; + int palsize; + + /* Verify the parameters */ + pal = screen->format->palette; + if (!pal) { + return 0; /* not a palettized surface */ + } + gotall = 1; + palsize = 1 << screen->format->BitsPerPixel; + if (ncolors > (palsize - firstcolor)) { + ncolors = (palsize - firstcolor); + gotall = 0; + } + + if (screen->flags & (SDL_SHADOW_SURFACE | SDL_SCREEN_SURFACE)) { + window = SDL_GetWindowFromSurface(screen); + if (!window) { + return 0; + } + } + + if (screen->flags & SDL_SHADOW_SURFACE) { + SDL_Palette *vidpal; + + vidpal = window->surface->format->palette; + if (vidpal && vidpal->ncolors == pal->ncolors) { + /* This is a shadow surface, and the physical + * framebuffer is also indexed. Propagate the + * changes to its logical palette so that + * updates are always identity blits + */ + SDL_memcpy(vidpal->colors + firstcolor, colors, + ncolors * sizeof(*colors)); + } + if (window->surface->flags & SDL_HWPALETTE) { + /* Set the physical palette */ + screen = window->surface; + } else { + SDL_UpdateRect(screen, 0, 0, 0, 0); + } + } + + if (screen->flags & SDL_SCREEN_SURFACE) { + if (_this->SetWindowColors) { + gotall = + _this->SetWindowColors(_this, window, firstcolor, ncolors, + colors); + if (!gotall) { + /* The video flags shouldn't have SDL_HWPALETTE, and + the video driver is responsible for copying back the + correct colors into the video surface palette. + */ + ; + } + } + SDL_CursorPaletteChanged(); + } + + return gotall; +} + int SDL_GetWMInfo(SDL_SysWMinfo * info) { return SDL_GetWindowWMInfo(window, info); } +void +SDL_MoveCursor(int x, int y) +{ + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + + /* Erase and update the current mouse position */ + if (SHOULD_DRAWCURSOR(SDL_cursorstate)) { + /* Erase and redraw mouse cursor in new position */ + SDL_LockCursor(); + SDL_EraseCursor(SDL_VideoSurface); + SDL_cursor->area.x = (x - SDL_cursor->hot_x); + SDL_cursor->area.y = (y - SDL_cursor->hot_y); + SDL_DrawCursor(SDL_VideoSurface); + SDL_UnlockCursor(); + } else if (_this->MoveWMCursor) { + _this->MoveWMCursor(_this, x, y); + } +} + +/* Keep track of the current cursor colors */ +static int palette_changed = 1; +static Uint8 pixels8[2]; + +void +SDL_CursorPaletteChanged(void) +{ + palette_changed = 1; +} + +void +SDL_MouseRect(SDL_Rect * area) +{ + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + int clip_diff; + + *area = SDL_cursor->area; + if (area->x < 0) { + area->w += area->x; + area->x = 0; + } + if (area->y < 0) { + area->h += area->y; + area->y = 0; + } + clip_diff = (area->x + area->w) - SDL_VideoSurface->w; + if (clip_diff > 0) { + area->w = area->w < clip_diff ? 0 : area->w - clip_diff; + } + clip_diff = (area->y + area->h) - SDL_VideoSurface->h; + if (clip_diff > 0) { + area->h = area->h < clip_diff ? 0 : area->h - clip_diff; + } +} + +static void +SDL_DrawCursorFast(SDL_Surface * screen, SDL_Rect * area) +{ + const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 }; + int i, w, h; + Uint8 *data, datab; + Uint8 *mask, maskb; + + data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8; + mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8; + switch (screen->format->BytesPerPixel) { + + case 1: + { + Uint8 *dst; + int dstskip; + + if (palette_changed) { + pixels8[0] = + (Uint8) SDL_MapRGB(screen->format, 255, 255, 255); + pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0); + palette_changed = 0; + } + dst = (Uint8 *) screen->pixels + + (SDL_cursor->area.y + area->y) * screen->pitch + + SDL_cursor->area.x; + dstskip = screen->pitch - area->w; + + for (h = area->h; h; h--) { + for (w = area->w / 8; w; w--) { + maskb = *mask++; + datab = *data++; + for (i = 0; i < 8; ++i) { + if (maskb & 0x80) { + *dst = pixels8[datab >> 7]; + } + maskb <<= 1; + datab <<= 1; + dst++; + } + } + dst += dstskip; + } + } + break; + + case 2: + { + Uint16 *dst; + int dstskip; + + dst = (Uint16 *) screen->pixels + + (SDL_cursor->area.y + area->y) * screen->pitch / 2 + + SDL_cursor->area.x; + dstskip = (screen->pitch / 2) - area->w; + + for (h = area->h; h; h--) { + for (w = area->w / 8; w; w--) { + maskb = *mask++; + datab = *data++; + for (i = 0; i < 8; ++i) { + if (maskb & 0x80) { + *dst = (Uint16) pixels[datab >> 7]; + } + maskb <<= 1; + datab <<= 1; + dst++; + } + } + dst += dstskip; + } + } + break; + + case 3: + { + Uint8 *dst; + int dstskip; + + dst = (Uint8 *) screen->pixels + + (SDL_cursor->area.y + area->y) * screen->pitch + + SDL_cursor->area.x * 3; + dstskip = screen->pitch - area->w * 3; + + for (h = area->h; h; h--) { + for (w = area->w / 8; w; w--) { + maskb = *mask++; + datab = *data++; + for (i = 0; i < 8; ++i) { + if (maskb & 0x80) { + SDL_memset(dst, pixels[datab >> 7], 3); + } + maskb <<= 1; + datab <<= 1; + dst += 3; + } + } + dst += dstskip; + } + } + break; + + case 4: + { + Uint32 *dst; + int dstskip; + + dst = (Uint32 *) screen->pixels + + (SDL_cursor->area.y + area->y) * screen->pitch / 4 + + SDL_cursor->area.x; + dstskip = (screen->pitch / 4) - area->w; + + for (h = area->h; h; h--) { + for (w = area->w / 8; w; w--) { + maskb = *mask++; + datab = *data++; + for (i = 0; i < 8; ++i) { + if (maskb & 0x80) { + *dst = pixels[datab >> 7]; + } + maskb <<= 1; + datab <<= 1; + dst++; + } + } + dst += dstskip; + } + } + break; + } +} + +static void +SDL_DrawCursorSlow(SDL_Surface * screen, SDL_Rect * area) +{ + const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 }; + int h; + int x, minx, maxx; + Uint8 *data, datab = 0; + Uint8 *mask, maskb = 0; + Uint8 *dst; + int dstbpp, dstskip; + + data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8; + mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8; + dstbpp = screen->format->BytesPerPixel; + dst = (Uint8 *) screen->pixels + + (SDL_cursor->area.y + area->y) * screen->pitch + + SDL_cursor->area.x * dstbpp; + dstskip = screen->pitch - SDL_cursor->area.w * dstbpp; + + minx = area->x; + maxx = area->x + area->w; + if (screen->format->BytesPerPixel == 1) { + if (palette_changed) { + pixels8[0] = (Uint8) SDL_MapRGB(screen->format, 255, 255, 255); + pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0); + palette_changed = 0; + } + for (h = area->h; h; h--) { + for (x = 0; x < SDL_cursor->area.w; ++x) { + if ((x % 8) == 0) { + maskb = *mask++; + datab = *data++; + } + if ((x >= minx) && (x < maxx)) { + if (maskb & 0x80) { + SDL_memset(dst, pixels8[datab >> 7], dstbpp); + } + } + maskb <<= 1; + datab <<= 1; + dst += dstbpp; + } + dst += dstskip; + } + } else { + for (h = area->h; h; h--) { + for (x = 0; x < SDL_cursor->area.w; ++x) { + if ((x % 8) == 0) { + maskb = *mask++; + datab = *data++; + } + if ((x >= minx) && (x < maxx)) { + if (maskb & 0x80) { + SDL_memset(dst, pixels[datab >> 7], dstbpp); + } + } + maskb <<= 1; + datab <<= 1; + dst += dstbpp; + } + dst += dstskip; + } + } +} + +/* This handles the ugly work of converting the saved cursor background from + the pixel format of the shadow surface to that of the video surface. + This is only necessary when blitting from a shadow surface of a different + pixel format than the video surface, and using a software rendered cursor. +*/ +static void +SDL_ConvertCursorSave(SDL_Surface * screen, int w, int h) +{ + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + SDL_BlitInfo info; + SDL_loblit RunBlit; + + /* Make sure we can steal the blit mapping */ + if (screen->map->dst != SDL_VideoSurface) { + return; + } + + /* Set up the blit information */ + info.s_pixels = SDL_cursor->save[1]; + info.s_width = w; + info.s_height = h; + info.s_skip = 0; + info.d_pixels = SDL_cursor->save[0]; + info.d_width = w; + info.d_height = h; + info.d_skip = 0; + info.aux_data = screen->map->sw_data->aux_data; + info.src = screen->format; + info.table = screen->map->table; + info.dst = SDL_VideoSurface->format; + RunBlit = screen->map->sw_data->blit; + + /* Run the actual software blit */ + RunBlit(&info); +} + +void +SDL_DrawCursorNoLock(SDL_Surface * screen) +{ + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + SDL_Rect area; + + /* Get the mouse rectangle, clipped to the screen */ + SDL_MouseRect(&area); + if ((area.w == 0) || (area.h == 0)) { + return; + } + + /* Copy mouse background */ + { + int w, h, screenbpp; + Uint8 *src, *dst; + + /* Set up the copy pointers */ + screenbpp = screen->format->BytesPerPixel; + if ((screen == SDL_VideoSurface) || + FORMAT_EQUAL(screen->format, SDL_VideoSurface->format)) { + dst = SDL_cursor->save[0]; + } else { + dst = SDL_cursor->save[1]; + } + src = (Uint8 *) screen->pixels + area.y * screen->pitch + + area.x * screenbpp; + + /* Perform the copy */ + w = area.w * screenbpp; + h = area.h; + while (h--) { + SDL_memcpy(dst, src, w); + dst += w; + src += screen->pitch; + } + } + + /* Draw the mouse cursor */ + area.x -= SDL_cursor->area.x; + area.y -= SDL_cursor->area.y; + if ((area.x == 0) && (area.w == SDL_cursor->area.w)) { + SDL_DrawCursorFast(screen, &area); + } else { + SDL_DrawCursorSlow(screen, &area); + } +} + +void +SDL_DrawCursor(SDL_Surface * screen) +{ + /* Lock the screen if necessary */ + if (screen == NULL) { + return; + } + if (SDL_MUSTLOCK(screen)) { + if (SDL_LockSurface(screen) < 0) { + return; + } + } + + SDL_DrawCursorNoLock(screen); + + /* Unlock the screen and update if necessary */ + if (SDL_MUSTLOCK(screen)) { + SDL_UnlockSurface(screen); + } + if ((screen->flags & SDL_SCREEN_SURFACE) && + !(screen->flags & SDL_HWSURFACE)) { + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + SDL_Window *window; + SDL_Rect area; + + window = SDL_GetWindowFromSurface(screen); + if (!window) { + return; + } + + SDL_MouseRect(&area); + + if (_this->UpdateWindowSurface) { + _this->UpdateWindowSurface(_this, window, 1, &area); + } + } +} + +void +SDL_EraseCursorNoLock(SDL_Surface * screen) +{ + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + SDL_Window *window; + SDL_Rect area; + + /* Get the window associated with the surface */ + window = SDL_GetWindowFromSurface(screen); + if (!window || !window->surface) { + return; + } + + /* Get the mouse rectangle, clipped to the screen */ + SDL_MouseRect(&area); + if ((area.w == 0) || (area.h == 0)) { + return; + } + + /* Copy mouse background */ + { + int w, h, screenbpp; + Uint8 *src, *dst; + + /* Set up the copy pointers */ + screenbpp = screen->format->BytesPerPixel; + if ((screen->flags & SDL_SCREEN_SURFACE) || + FORMAT_EQUAL(screen->format, window->surface->format)) { + src = SDL_cursor->save[0]; + } else { + src = SDL_cursor->save[1]; + } + dst = (Uint8 *) screen->pixels + area.y * screen->pitch + + area.x * screenbpp; + + /* Perform the copy */ + w = area.w * screenbpp; + h = area.h; + while (h--) { + SDL_memcpy(dst, src, w); + src += w; + dst += screen->pitch; + } + + /* Perform pixel conversion on cursor background */ + if (src > SDL_cursor->save[1]) { + SDL_ConvertCursorSave(screen, area.w, area.h); + } + } +} + +void +SDL_EraseCursor(SDL_Surface * screen) +{ + /* Lock the screen if necessary */ + if (screen == NULL) { + return; + } + if (SDL_MUSTLOCK(screen)) { + if (SDL_LockSurface(screen) < 0) { + return; + } + } + + SDL_EraseCursorNoLock(screen); + + /* Unlock the screen and update if necessary */ + if (SDL_MUSTLOCK(screen)) { + SDL_UnlockSurface(screen); + } + if ((screen->flags & SDL_SCREEN_SURFACE) && + !(screen->flags & SDL_HWSURFACE)) { + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + SDL_Window *window; + SDL_Rect area; + + window = SDL_GetWindowFromSurface(screen); + if (!window) { + return; + } + + SDL_MouseRect(&area); + + if (_this->UpdateWindowSurface) { + _this->UpdateWindowSurface(_this, window, 1, &area); + } + } +} + +/* Reset the cursor on video mode change + FIXME: Keep track of all cursors, and reset them all. + */ +void +SDL_ResetCursor(void) +{ + int savelen; + + if (SDL_cursor) { + savelen = SDL_cursor->area.w * 4 * SDL_cursor->area.h; + SDL_cursor->area.x = 0; + SDL_cursor->area.y = 0; + SDL_memset(SDL_cursor->save[0], 0, savelen); + } +} + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/events/SDL_events_c.h b/src/events/SDL_events_c.h index da0a9c2c6..0dc3fef69 100644 --- a/src/events/SDL_events_c.h +++ b/src/events/SDL_events_c.h @@ -23,6 +23,7 @@ /* Useful functions and variables from SDL_events.c */ #include "SDL_events.h" +#include "SDL_mouse_c.h" /* Start and stop the event processing loop */ extern int SDL_StartEventLoop(Uint32 flags); @@ -33,41 +34,25 @@ extern void SDL_Lock_EventThread(void); extern void SDL_Unlock_EventThread(void); extern Uint32 SDL_EventThreadID(void); -/* Event handler init routines */ extern int SDL_KeyboardInit(void); -extern int SDL_MouseInit(void); -extern int SDL_QuitInit(void); - -/* Event handler quit routines */ +extern int SDL_SendKeyboard(Uint8 state, SDL_keysym * key); extern void SDL_KeyboardQuit(void); -extern void SDL_MouseQuit(void); + +extern int SDL_QuitInit(void); +extern int SDL_SendQuit(void); extern void SDL_QuitQuit(void); +extern int SDL_SendWindowEvent(SDL_WindowID windowID, Uint8 windowevent, + int data1, int data2); + +extern int SDL_SendSysWMEvent(SDL_SysWMmsg * message); + /* The event filter function */ extern SDL_EventFilter SDL_EventOK; /* The array of event processing states */ extern Uint8 SDL_ProcessEvents[SDL_NUMEVENTS]; -/* Internal event queueing functions - (from SDL_mouse.c, SDL_keyboard.c, SDL_quit.c, SDL_events.c, SDL_windowevents.c) - */ -extern int SDL_PrivateWindowEvent(SDL_WindowID windowID, Uint8 windowevent, - int data1, int data2); -extern int SDL_PrivateMouseMotion(Uint8 buttonstate, int relative, Sint16 x, - Sint16 y); -extern int SDL_PrivateMouseButton(Uint8 state, Uint8 button, Sint16 x, - Sint16 y); -extern int SDL_PrivateKeyboard(Uint8 state, SDL_keysym * key); -extern int SDL_PrivateQuit(void); -extern int SDL_PrivateSysWMEvent(SDL_SysWMmsg * message); - -/* Used by the activity event handler to remove mouse focus */ -extern void SDL_ResetMouse(void); - -/* Used by the activity event handler to remove keyboard focus */ -extern void SDL_ResetKeyboard(void); - /* Used by the event loop to queue pending keyboard repeat events */ extern void SDL_CheckKeyRepeat(void); diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index a2ca0828e..c4a837ef1 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -326,7 +326,7 @@ SDL_ResetKeyboard(void) for (key = SDLK_FIRST; key < SDLK_LAST; ++key) { if (SDL_KeyState[key] == SDL_PRESSED) { keysym.sym = key; - SDL_PrivateKeyboard(SDL_RELEASED, &keysym); + SDL_SendKeyboard(SDL_RELEASED, &keysym); } } SDL_KeyRepeat.timestamp = 0; @@ -382,7 +382,7 @@ SDL_GetKeyName(SDLKey key) /* These are global for SDL_eventloop.c */ int -SDL_PrivateKeyboard(Uint8 state, SDL_keysym * keysym) +SDL_SendKeyboard(Uint8 state, SDL_keysym * keysym) { SDL_Event event; int posted, repeatable; diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index c82573766..80e7fc8e7 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -25,249 +25,261 @@ #include "SDL_events.h" #include "SDL_events_c.h" -#include "../video/SDL_cursor_c.h" -#include "../video/SDL_sysvideo.h" +#include "SDL_mouse_c.h" -/* These are static for our mouse handling code */ -static Sint16 SDL_MouseX = 0; -static Sint16 SDL_MouseY = 0; -static Sint16 SDL_DeltaX = 0; -static Sint16 SDL_DeltaY = 0; -static Uint8 SDL_ButtonState = 0; +static int SDL_num_mice; +static int SDL_current_mouse; +static SDL_Mouse *SDL_mice; /* Public functions */ int SDL_MouseInit(void) { - /* The mouse is at (0,0) */ - SDL_MouseX = 0; - SDL_MouseY = 0; - SDL_DeltaX = 0; - SDL_DeltaY = 0; - SDL_ButtonState = 0; - - /* That's it! */ return (0); } +int +SDL_AddMouse(SDL_WindowID focus, int x, int y, Uint8 buttonstate) +{ + SDL_Mouse *new_mice; + int index; + SDL_Mouse *mouse; + + new_mice = + (SDL_Mouse *) SDL_realloc(SDL_mice, + (SDL_num_mice + 1) * sizeof(*new_mice)); + if (!new_mice) { + SDL_OutOfMemory(); + return -1; + } + + index = SDL_num_mice++; + mouse = &SDL_mice[index]; + mouse->focus = focus; + mouse->x = x; + mouse->y = y; + mouse->xdelta = 0; + mouse->ydelta = 0; + mouse->buttonstate = buttonstate; + + return index; +} + +SDL_Mouse * +SDL_GetMouse(int index) +{ + if (index < 0 || index >= SDL_num_mice) { + return NULL; + } + return &SDL_mice[index]; +} + void SDL_MouseQuit(void) { + SDL_num_mice = 0; + SDL_current_mouse = 0; + + if (SDL_mice) { + SDL_free(SDL_mice); + SDL_mice = NULL; + } +} + +int +SDL_GetNumMice(void) +{ + return SDL_num_mice; } -/* We lost the mouse, so post button up messages for all pressed buttons */ -void -SDL_ResetMouse(void) +int +SDL_SelectMouse(int index) { - Uint8 i; - for (i = 0; i < sizeof(SDL_ButtonState) * 8; ++i) { - if (SDL_ButtonState & SDL_BUTTON(i)) { - SDL_PrivateMouseButton(SDL_RELEASED, i, 0, 0); - } + if (index >= 0 && index < SDL_num_mice) { + SDL_current_mouse = index; } + return SDL_current_mouse; +} + +SDL_WindowID +SDL_GetMouseFocusWindow() +{ + SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); + + if (!mouse) { + return 0; + } + return mouse->focus; } Uint8 SDL_GetMouseState(int *x, int *y) { + SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); + + if (!mouse) { + if (x) { + *x = 0; + } + if (y) { + *y = 0; + } + return 0; + } + if (x) { - *x = SDL_MouseX; + *x = mouse->x; } if (y) { - *y = SDL_MouseY; + *y = mouse->y; } - return (SDL_ButtonState); + return mouse->buttonstate; } Uint8 SDL_GetRelativeMouseState(int *x, int *y) { - if (x) - *x = SDL_DeltaX; - if (y) - *y = SDL_DeltaY; - SDL_DeltaX = 0; - SDL_DeltaY = 0; - return (SDL_ButtonState); -} + SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); -static void -ClipOffset(Sint16 * x, Sint16 * y) -{ - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - - /* This clips absolute mouse coordinates when the apparent - display surface is smaller than the real display surface. - */ - if (SDL_VideoSurface->offset) { - *y -= SDL_VideoSurface->offset / SDL_VideoSurface->pitch; - *x -= (SDL_VideoSurface->offset % SDL_VideoSurface->pitch) / - SDL_VideoSurface->format->BytesPerPixel; + if (!mouse) { + if (x) { + *x = 0; + } + if (y) { + *y = 0; + } + return 0; + } + + if (x) { + *x = mouse->xdelta; + } + if (y) { + *y = mouse->ydelta; } + mouse->xdelta = 0; + mouse->ydelta = 0; + return mouse->buttonstate; } -/* These are global for SDL_eventloop.c */ int -SDL_PrivateMouseMotion(Uint8 buttonstate, int relative, Sint16 x, Sint16 y) +SDL_SendMouseMotion(int index, SDL_WindowID windowID, int relative, int x, + int y) { - SDL_VideoDevice *_this = SDL_GetVideoDevice(); + SDL_Mouse *mouse = SDL_GetMouse(index); int posted; - Uint16 X, Y; - Sint16 Xrel; - Sint16 Yrel; + int xrel; + int yrel; - /* Don't handle mouse motion if there's no cursor surface */ - if (SDL_VideoSurface == NULL) { - return (0); + if (!mouse) { + return 0; } - /* Default buttonstate is the current one */ - if (!buttonstate) { - buttonstate = SDL_ButtonState; + if (windowID) { + mouse->focus = windowID; } - Xrel = x; - Yrel = y; if (relative) { /* Push the cursor around */ - x = (SDL_MouseX + x); - y = (SDL_MouseY + y); + xrel = x; + yrel = y; + x = (mouse->x + xrel); + y = (mouse->y + yrel); } else { - /* Do we need to clip {x,y} ? */ - ClipOffset(&x, &y); - } - - /* Mouse coordinates range from 0 - width-1 and 0 - height-1 */ - if (x < 0) - X = 0; - else if (x >= SDL_VideoSurface->w) - X = SDL_VideoSurface->w - 1; - else - X = (Uint16) x; - - if (y < 0) - Y = 0; - else if (y >= SDL_VideoSurface->h) - Y = SDL_VideoSurface->h - 1; - else - Y = (Uint16) y; - - /* If not relative mode, generate relative motion from clamped X/Y. - This prevents lots of extraneous large delta relative motion when - the screen is windowed mode and the mouse is outside the window. - */ - if (!relative) { - Xrel = X - SDL_MouseX; - Yrel = Y - SDL_MouseY; + xrel = x - mouse->x; + yrel = y - mouse->y; } /* Drop events that don't change state */ - if (!Xrel && !Yrel) { + if (!xrel && !yrel) { #if 0 printf("Mouse event didn't change state - dropped!\n"); #endif - return (0); + return 0; } /* Update internal mouse state */ - SDL_ButtonState = buttonstate; - SDL_MouseX = X; - SDL_MouseY = Y; - SDL_DeltaX += Xrel; - SDL_DeltaY += Yrel; - SDL_MoveCursor(SDL_MouseX, SDL_MouseY); + mouse->xdelta += xrel; + mouse->ydelta += yrel; /* Post the event, if desired */ posted = 0; if (SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE) { SDL_Event event; - SDL_memset(&event, 0, sizeof(event)); - event.type = SDL_MOUSEMOTION; - event.motion.state = buttonstate; - event.motion.x = X; - event.motion.y = Y; - event.motion.xrel = Xrel; - event.motion.yrel = Yrel; + event.motion.type = SDL_MOUSEMOTION; + event.motion.which = (Uint8) index; + event.motion.state = mouse->buttonstate; + event.motion.x = mouse->x; + event.motion.y = mouse->y; + event.motion.xrel = xrel; + event.motion.yrel = yrel; + event.motion.windowID = mouse->focus; if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) { posted = 1; SDL_PushEvent(&event); } } - return (posted); + return posted; } int -SDL_PrivateMouseButton(Uint8 state, Uint8 button, Sint16 x, Sint16 y) +SDL_PrivateMouseButton(int index, SDL_WindowID windowID, Uint8 state, + Uint8 button) { - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - SDL_Event event; + SDL_Mouse *mouse = SDL_GetMouse(index); int posted; - int move_mouse; - Uint8 buttonstate; - - SDL_memset(&event, 0, sizeof(event)); - - /* Check parameters */ - if (x || y) { - ClipOffset(&x, &y); - move_mouse = 1; - /* Mouse coordinates range from 0 - width-1 and 0 - height-1 */ - if (x < 0) - x = 0; - else if (x >= SDL_VideoSurface->w) - x = SDL_VideoSurface->w - 1; - - if (y < 0) - y = 0; - else if (y >= SDL_VideoSurface->h) - y = SDL_VideoSurface->h - 1; - } else { - move_mouse = 0; + Uint8 type; + + if (!mouse) { + return 0; + } + + if (windowID) { + mouse->focus = windowID; } - if (!x) - x = SDL_MouseX; - if (!y) - y = SDL_MouseY; /* Figure out which event to perform */ - buttonstate = SDL_ButtonState; switch (state) { case SDL_PRESSED: - event.type = SDL_MOUSEBUTTONDOWN; - buttonstate |= SDL_BUTTON(button); + if (mouse->buttonstate & SDL_BUTTON(button)) { + /* Ignore this event, no state change */ + return 0; + } + type = SDL_MOUSEBUTTONDOWN; + mouse->buttonstate |= SDL_BUTTON(button); break; case SDL_RELEASED: - event.type = SDL_MOUSEBUTTONUP; - buttonstate &= ~SDL_BUTTON(button); + if (!(mouse->buttonstate & SDL_BUTTON(button))) { + /* Ignore this event, no state change */ + return 0; + } + type = SDL_MOUSEBUTTONUP; + mouse->buttonstate &= ~SDL_BUTTON(button); break; default: /* Invalid state -- bail */ - return (0); - } - - /* Update internal mouse state */ - SDL_ButtonState = buttonstate; - if (move_mouse) { - SDL_MouseX = x; - SDL_MouseY = y; - SDL_MoveCursor(SDL_MouseX, SDL_MouseY); + return 0; } /* Post the event, if desired */ posted = 0; - if (SDL_ProcessEvents[event.type] == SDL_ENABLE) { + if (SDL_ProcessEvents[type] == SDL_ENABLE) { + SDL_Event event; + event.type = type; + event.button.which = (Uint8) index; event.button.state = state; event.button.button = button; - event.button.x = x; - event.button.y = y; + event.button.x = mouse->x; + event.button.y = mouse->y; + event.button.windowID = windowID; if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) { posted = 1; SDL_PushEvent(&event); } } - return (posted); + return posted; } /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h new file mode 100644 index 000000000..ac2225517 --- /dev/null +++ b/src/events/SDL_mouse_c.h @@ -0,0 +1,48 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2006 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_mouse_c_h +#define _SDL_mouse_c_h + +typedef struct +{ + SDL_WindowID focus; + int x; + int y; + int xdelta; + int ydelta; + Uint8 buttonstate; +} SDL_Mouse; + +extern int SDL_MouseInit(void); +extern int SDL_AddMouse(SDL_WindowID focus, int x, int y, Uint8 buttonstate); +extern SDL_Mouse *SDL_GetMouse(int index); +extern int SDL_SendMouseMotion(int index, SDL_WindowID windowID, int relative, + int x, int y); +extern int SDL_SendMouseButton(int index, SDL_WindowID windowID, Uint8 state, + Uint8 button); +extern void SDL_MouseQuit(void); + +#endif /* _SDL_mouse_c_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/events/SDL_quit.c b/src/events/SDL_quit.c index b361301de..e8fe56abd 100644 --- a/src/events/SDL_quit.c +++ b/src/events/SDL_quit.c @@ -39,7 +39,7 @@ SDL_HandleSIG(int sig) signal(sig, SDL_HandleSIG); /* Signal a quit interrupt */ - SDL_PrivateQuit(); + SDL_SendQuit(); } #endif /* HAVE_SIGNAL_H */ @@ -80,7 +80,7 @@ SDL_QuitQuit(void) /* This function returns 1 if it's okay to close the application window */ int -SDL_PrivateQuit(void) +SDL_SendQuit(void) { int posted; diff --git a/src/video/SDL_blit.c b/src/video/SDL_blit.c index 957504638..b1bac06a5 100644 --- a/src/video/SDL_blit.c +++ b/src/video/SDL_blit.c @@ -217,8 +217,6 @@ SDL_BlitCopyOverlap(SDL_BlitInfo * info) int SDL_CalculateBlit(SDL_Surface * surface) { - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - const SDL_VideoInfo *info = SDL_GetVideoInfo(); int blit_index; /* Clean everything out to start */ @@ -227,52 +225,6 @@ SDL_CalculateBlit(SDL_Surface * surface) } surface->map->sw_blit = NULL; - /* Figure out if an accelerated hardware blit is possible */ - surface->flags &= ~SDL_HWACCEL; - if (surface->map->identity) { - int hw_blit_ok; - - if ((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE) { - /* We only support accelerated blitting to hardware */ - if (surface->map->dst->flags & SDL_HWSURFACE) { - hw_blit_ok = info->blit_hw; - } else { - hw_blit_ok = 0; - } - if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { - hw_blit_ok = info->blit_hw_CC; - } - if (hw_blit_ok && (surface->flags & SDL_SRCALPHA)) { - hw_blit_ok = info->blit_hw_A; - } - } else { - /* We only support accelerated blitting to hardware */ - if (surface->map->dst->flags & SDL_HWSURFACE) { - hw_blit_ok = info->blit_sw; - } else { - hw_blit_ok = 0; - } - if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { - hw_blit_ok = info->blit_sw_CC; - } - if (hw_blit_ok && (surface->flags & SDL_SRCALPHA)) { - hw_blit_ok = info->blit_sw_A; - } - } - if (hw_blit_ok) { - _this->CheckHWBlit(_this, surface, surface->map->dst); - } - } - - /* if an alpha pixel format is specified, we can accelerate alpha blits */ - if (((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE) - && (_this->displayformatalphapixel)) { - if ((surface->flags & SDL_SRCALPHA)) - if (info->blit_hw_A) { - _this->CheckHWBlit(_this, surface, surface->map->dst); - } - } - /* Get the blit function index, based on surface mode */ /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */ blit_index = 0; @@ -321,9 +273,7 @@ SDL_CalculateBlit(SDL_Surface * surface) } /* Choose software blitting function */ - if (surface->flags & SDL_RLEACCELOK - && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) { - + if (surface->flags & SDL_RLEACCELOK) { if (surface->map->identity && (blit_index == 1 || (blit_index == 3 && !surface->format->Amask))) { diff --git a/src/video/SDL_bmp.c b/src/video/SDL_bmp.c index a30a84855..e2fe336ff 100644 --- a/src/video/SDL_bmp.c +++ b/src/video/SDL_bmp.c @@ -203,9 +203,9 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc) } /* Create a compatible surface, note that the colors are RGB ordered */ - surface = SDL_CreateRGBSurface(SDL_SWSURFACE, - biWidth, biHeight, biBitCount, Rmask, - Gmask, Bmask, 0); + surface = + SDL_CreateRGBSurface(0, biWidth, biHeight, biBitCount, Rmask, Gmask, + Bmask, 0); if (surface == NULL) { was_error = 1; goto done; @@ -386,8 +386,7 @@ SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst) SDL_Rect bounds; /* Convert to 24 bits per pixel */ - surface = SDL_CreateRGBSurface(SDL_SWSURFACE, - saveme->w, saveme->h, 24, + surface = SDL_CreateRGBSurface(0, saveme->w, saveme->h, 24, #if SDL_BYTEORDER == SDL_LIL_ENDIAN 0x00FF0000, 0x0000FF00, 0x000000FF, #else diff --git a/src/video/SDL_cursor.c b/src/video/SDL_cursor.c index f7a549f8b..b0b3b5268 100644 --- a/src/video/SDL_cursor.c +++ b/src/video/SDL_cursor.c @@ -23,22 +23,17 @@ /* General cursor handling code for SDL */ -#include "SDL_mutex.h" #include "SDL_video.h" #include "SDL_mouse.h" -#include "SDL_blit.h" #include "SDL_sysvideo.h" #include "SDL_cursor_c.h" -#include "SDL_pixels_c.h" #include "default_cursor.h" -#include "../events/SDL_sysevents.h" -#include "../events/SDL_events_c.h" /* These are static for our cursor handling code */ +/* FIXME: Add support for multiple simultaneous cursors */ volatile int SDL_cursorstate = CURSOR_VISIBLE; SDL_Cursor *SDL_cursor = NULL; static SDL_Cursor *SDL_defcursor = NULL; -SDL_mutex *SDL_cursorlock = NULL; /* Public functions */ void @@ -58,13 +53,10 @@ SDL_CursorQuit(void) SDL_FreeCursor(cursor); } } - if (SDL_cursorlock != NULL) { - SDL_DestroyMutex(SDL_cursorlock); - SDL_cursorlock = NULL; - } } + int -SDL_CursorInit(Uint32 multithreaded) +SDL_CursorInit(void) { /* We don't have mouse focus, and the cursor isn't drawn yet */ #ifndef IPOD @@ -79,43 +71,15 @@ SDL_CursorInit(Uint32 multithreaded) SDL_SetCursor(SDL_defcursor); } - /* Create a lock if necessary */ - if (multithreaded) { - SDL_cursorlock = SDL_CreateMutex(); - } - /* That's it! */ return (0); } -/* Multi-thread support for cursors */ -#ifndef SDL_LockCursor -void -SDL_LockCursor(void) -{ - if (SDL_cursorlock) { - SDL_mutexP(SDL_cursorlock); - } -} -#endif -#ifndef SDL_UnlockCursor -void -SDL_UnlockCursor(void) -{ - if (SDL_cursorlock) { - SDL_mutexV(SDL_cursorlock); - } -} -#endif - -/* Software cursor drawing support */ SDL_Cursor * SDL_CreateCursor(Uint8 * data, Uint8 * mask, int w, int h, int hot_x, int hot_y) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); - int savelen; - int i; SDL_Cursor *cursor; /* Make sure the width is a multiple of 8 */ @@ -127,41 +91,10 @@ SDL_CreateCursor(Uint8 * data, Uint8 * mask, return (NULL); } - /* Allocate memory for the cursor */ - cursor = (SDL_Cursor *) SDL_malloc(sizeof *cursor); - if (cursor == NULL) { - SDL_OutOfMemory(); - return (NULL); - } - savelen = (w * 4) * h; - cursor->area.x = 0; - cursor->area.y = 0; - cursor->area.w = w; - cursor->area.h = h; - cursor->hot_x = hot_x; - cursor->hot_y = hot_y; - cursor->data = (Uint8 *) SDL_malloc((w / 8) * h * 2); - cursor->mask = cursor->data + ((w / 8) * h); - cursor->save[0] = (Uint8 *) SDL_malloc(savelen * 2); - cursor->save[1] = cursor->save[0] + savelen; - cursor->wm_cursor = NULL; - if (!cursor->data || !cursor->save[0]) { - SDL_FreeCursor(cursor); - SDL_OutOfMemory(); - return (NULL); - } - for (i = ((w / 8) * h) - 1; i >= 0; --i) { - cursor->data[i] = data[i]; - cursor->mask[i] = mask[i] | data[i]; - } - SDL_memset(cursor->save[0], 0, savelen * 2); - - /* If the window manager gives us a good cursor, we're done! */ if (_this->CreateWMCursor) { - cursor->wm_cursor = _this->CreateWMCursor(_this, data, mask, - w, h, hot_x, hot_y); + cursor = _this->CreateWMCursor(_this, data, mask, w, h, hot_x, hot_y); } else { - cursor->wm_cursor = NULL; + cursor = NULL; } return (cursor); } @@ -180,56 +113,22 @@ SDL_SetCursor(SDL_Cursor * cursor) return; } - /* Prevent the event thread from moving the mouse */ - SDL_LockCursor(); - /* Set the new cursor */ if (cursor && (cursor != SDL_cursor)) { - /* Erase the current mouse position */ - if (SHOULD_DRAWCURSOR(SDL_cursorstate)) { - SDL_EraseCursor(SDL_VideoSurface); - } else if (_this->MoveWMCursor) { - /* If the video driver is moving the cursor directly, - it needs to hide the old cursor before (possibly) - showing the new one. (But don't erase NULL cursor) - */ - if (SDL_cursor) { - _this->ShowWMCursor(_this, NULL); - } - } SDL_cursor = cursor; } /* Draw the new mouse cursor */ if (SDL_cursor && (SDL_cursorstate & CURSOR_VISIBLE)) { - /* Use window manager cursor if possible */ - if (SDL_cursor->wm_cursor && - _this->ShowWMCursor(_this, SDL_cursor->wm_cursor)) { - SDL_cursorstate &= ~CURSOR_USINGSW; - } else { - SDL_cursorstate |= CURSOR_USINGSW; - if (_this->ShowWMCursor) { - _this->ShowWMCursor(_this, NULL); - } - { - int x, y; - SDL_GetMouseState(&x, &y); - SDL_cursor->area.x = (x - SDL_cursor->hot_x); - SDL_cursor->area.y = (y - SDL_cursor->hot_y); - } - SDL_DrawCursor(SDL_VideoSurface); + if (_this->ShowWMCursor) { + _this->ShowWMCursor(_this, SDL_cursor); } } else { /* Erase window manager mouse (cursor not visible) */ - if (SDL_cursor && (SDL_cursorstate & CURSOR_USINGSW)) { - SDL_EraseCursor(SDL_VideoSurface); - } else { - if (_this) { - _this->ShowWMCursor(_this, NULL); - } + if (_this->ShowWMCursor) { + _this->ShowWMCursor(_this, NULL); } } - SDL_UnlockCursor(); } SDL_Cursor * @@ -248,16 +147,9 @@ SDL_FreeCursor(SDL_Cursor * cursor) if (cursor != SDL_defcursor) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); - if (cursor->data) { - SDL_free(cursor->data); + if (_this && _this->FreeWMCursor) { + _this->FreeWMCursor(_this, cursor); } - if (cursor->save[0]) { - SDL_free(cursor->save[0]); - } - if (_this && cursor->wm_cursor) { - _this->FreeWMCursor(_this, cursor->wm_cursor); - } - SDL_free(cursor); } } } @@ -269,13 +161,11 @@ SDL_ShowCursor(int toggle) showing = (SDL_cursorstate & CURSOR_VISIBLE); if (toggle >= 0) { - SDL_LockCursor(); if (toggle) { SDL_cursorstate |= CURSOR_VISIBLE; } else { SDL_cursorstate &= ~CURSOR_VISIBLE; } - SDL_UnlockCursor(); if ((SDL_cursorstate & CURSOR_VISIBLE) != showing) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); @@ -291,509 +181,23 @@ SDL_ShowCursor(int toggle) } void -SDL_WarpMouse(Uint16 x, Uint16 y) +SDL_WarpMouseInWindow(SDL_WindowID windowID, int x, int y) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); - if (!_this || !SDL_PublicSurface) { - SDL_SetError("A video mode must be set before warping mouse"); + /* FIXME: This should specify the target window */ + if (!_this || !SDL_CurrentDisplay.num_windows) { + SDL_SetError("A window must be created before warping mouse"); return; } - /* If we have an offset video mode, offset the mouse coordinates */ - if (SDL_VideoSurface->pitch == 0) { - x += SDL_VideoSurface->offset / - SDL_VideoSurface->format->BytesPerPixel; - y += SDL_VideoSurface->offset; - } else { - x += (SDL_VideoSurface->offset % SDL_VideoSurface->pitch) / - SDL_VideoSurface->format->BytesPerPixel; - y += (SDL_VideoSurface->offset / SDL_VideoSurface->pitch); + if (!windowID) { + windowID = SDL_CurrentWindow; } /* This generates a mouse motion event */ if (_this->WarpWMCursor) { - _this->WarpWMCursor(_this, x, y); - } else { - SDL_PrivateMouseMotion(0, 0, x, y); - } -} - -void -SDL_MoveCursor(int x, int y) -{ - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - - /* Erase and update the current mouse position */ - if (SHOULD_DRAWCURSOR(SDL_cursorstate)) { - /* Erase and redraw mouse cursor in new position */ - SDL_LockCursor(); - SDL_EraseCursor(SDL_VideoSurface); - SDL_cursor->area.x = (x - SDL_cursor->hot_x); - SDL_cursor->area.y = (y - SDL_cursor->hot_y); - SDL_DrawCursor(SDL_VideoSurface); - SDL_UnlockCursor(); - } else if (_this->MoveWMCursor) { - _this->MoveWMCursor(_this, x, y); - } -} - -/* Keep track of the current cursor colors */ -static int palette_changed = 1; -static Uint8 pixels8[2]; - -void -SDL_CursorPaletteChanged(void) -{ - palette_changed = 1; -} - -void -SDL_MouseRect(SDL_Rect * area) -{ - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - int clip_diff; - - *area = SDL_cursor->area; - if (area->x < 0) { - area->w += area->x; - area->x = 0; - } - if (area->y < 0) { - area->h += area->y; - area->y = 0; - } - clip_diff = (area->x + area->w) - SDL_VideoSurface->w; - if (clip_diff > 0) { - area->w = area->w < clip_diff ? 0 : area->w - clip_diff; - } - clip_diff = (area->y + area->h) - SDL_VideoSurface->h; - if (clip_diff > 0) { - area->h = area->h < clip_diff ? 0 : area->h - clip_diff; - } -} - -static void -SDL_DrawCursorFast(SDL_Surface * screen, SDL_Rect * area) -{ - const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 }; - int i, w, h; - Uint8 *data, datab; - Uint8 *mask, maskb; - - data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8; - mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8; - switch (screen->format->BytesPerPixel) { - - case 1: - { - Uint8 *dst; - int dstskip; - - if (palette_changed) { - pixels8[0] = - (Uint8) SDL_MapRGB(screen->format, 255, 255, 255); - pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0); - palette_changed = 0; - } - dst = (Uint8 *) screen->pixels + - (SDL_cursor->area.y + area->y) * screen->pitch + - SDL_cursor->area.x; - dstskip = screen->pitch - area->w; - - for (h = area->h; h; h--) { - for (w = area->w / 8; w; w--) { - maskb = *mask++; - datab = *data++; - for (i = 0; i < 8; ++i) { - if (maskb & 0x80) { - *dst = pixels8[datab >> 7]; - } - maskb <<= 1; - datab <<= 1; - dst++; - } - } - dst += dstskip; - } - } - break; - - case 2: - { - Uint16 *dst; - int dstskip; - - dst = (Uint16 *) screen->pixels + - (SDL_cursor->area.y + area->y) * screen->pitch / 2 + - SDL_cursor->area.x; - dstskip = (screen->pitch / 2) - area->w; - - for (h = area->h; h; h--) { - for (w = area->w / 8; w; w--) { - maskb = *mask++; - datab = *data++; - for (i = 0; i < 8; ++i) { - if (maskb & 0x80) { - *dst = (Uint16) pixels[datab >> 7]; - } - maskb <<= 1; - datab <<= 1; - dst++; - } - } - dst += dstskip; - } - } - break; - - case 3: - { - Uint8 *dst; - int dstskip; - - dst = (Uint8 *) screen->pixels + - (SDL_cursor->area.y + area->y) * screen->pitch + - SDL_cursor->area.x * 3; - dstskip = screen->pitch - area->w * 3; - - for (h = area->h; h; h--) { - for (w = area->w / 8; w; w--) { - maskb = *mask++; - datab = *data++; - for (i = 0; i < 8; ++i) { - if (maskb & 0x80) { - SDL_memset(dst, pixels[datab >> 7], 3); - } - maskb <<= 1; - datab <<= 1; - dst += 3; - } - } - dst += dstskip; - } - } - break; - - case 4: - { - Uint32 *dst; - int dstskip; - - dst = (Uint32 *) screen->pixels + - (SDL_cursor->area.y + area->y) * screen->pitch / 4 + - SDL_cursor->area.x; - dstskip = (screen->pitch / 4) - area->w; - - for (h = area->h; h; h--) { - for (w = area->w / 8; w; w--) { - maskb = *mask++; - datab = *data++; - for (i = 0; i < 8; ++i) { - if (maskb & 0x80) { - *dst = pixels[datab >> 7]; - } - maskb <<= 1; - datab <<= 1; - dst++; - } - } - dst += dstskip; - } - } - break; - } -} - -static void -SDL_DrawCursorSlow(SDL_Surface * screen, SDL_Rect * area) -{ - const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 }; - int h; - int x, minx, maxx; - Uint8 *data, datab = 0; - Uint8 *mask, maskb = 0; - Uint8 *dst; - int dstbpp, dstskip; - - data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8; - mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8; - dstbpp = screen->format->BytesPerPixel; - dst = (Uint8 *) screen->pixels + - (SDL_cursor->area.y + area->y) * screen->pitch + - SDL_cursor->area.x * dstbpp; - dstskip = screen->pitch - SDL_cursor->area.w * dstbpp; - - minx = area->x; - maxx = area->x + area->w; - if (screen->format->BytesPerPixel == 1) { - if (palette_changed) { - pixels8[0] = (Uint8) SDL_MapRGB(screen->format, 255, 255, 255); - pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0); - palette_changed = 0; - } - for (h = area->h; h; h--) { - for (x = 0; x < SDL_cursor->area.w; ++x) { - if ((x % 8) == 0) { - maskb = *mask++; - datab = *data++; - } - if ((x >= minx) && (x < maxx)) { - if (maskb & 0x80) { - SDL_memset(dst, pixels8[datab >> 7], dstbpp); - } - } - maskb <<= 1; - datab <<= 1; - dst += dstbpp; - } - dst += dstskip; - } - } else { - for (h = area->h; h; h--) { - for (x = 0; x < SDL_cursor->area.w; ++x) { - if ((x % 8) == 0) { - maskb = *mask++; - datab = *data++; - } - if ((x >= minx) && (x < maxx)) { - if (maskb & 0x80) { - SDL_memset(dst, pixels[datab >> 7], dstbpp); - } - } - maskb <<= 1; - datab <<= 1; - dst += dstbpp; - } - dst += dstskip; - } - } -} - -/* This handles the ugly work of converting the saved cursor background from - the pixel format of the shadow surface to that of the video surface. - This is only necessary when blitting from a shadow surface of a different - pixel format than the video surface, and using a software rendered cursor. -*/ -static void -SDL_ConvertCursorSave(SDL_Surface * screen, int w, int h) -{ - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - SDL_BlitInfo info; - SDL_loblit RunBlit; - - /* Make sure we can steal the blit mapping */ - if (screen->map->dst != SDL_VideoSurface) { - return; - } - - /* Set up the blit information */ - info.s_pixels = SDL_cursor->save[1]; - info.s_width = w; - info.s_height = h; - info.s_skip = 0; - info.d_pixels = SDL_cursor->save[0]; - info.d_width = w; - info.d_height = h; - info.d_skip = 0; - info.aux_data = screen->map->sw_data->aux_data; - info.src = screen->format; - info.table = screen->map->table; - info.dst = SDL_VideoSurface->format; - RunBlit = screen->map->sw_data->blit; - - /* Run the actual software blit */ - RunBlit(&info); -} - -void -SDL_DrawCursorNoLock(SDL_Surface * screen) -{ - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - SDL_Rect area; - - /* Get the mouse rectangle, clipped to the screen */ - SDL_MouseRect(&area); - if ((area.w == 0) || (area.h == 0)) { - return; - } - - /* Copy mouse background */ - { - int w, h, screenbpp; - Uint8 *src, *dst; - - /* Set up the copy pointers */ - screenbpp = screen->format->BytesPerPixel; - if ((screen == SDL_VideoSurface) || - FORMAT_EQUAL(screen->format, SDL_VideoSurface->format)) { - dst = SDL_cursor->save[0]; - } else { - dst = SDL_cursor->save[1]; - } - src = (Uint8 *) screen->pixels + area.y * screen->pitch + - area.x * screenbpp; - - /* Perform the copy */ - w = area.w * screenbpp; - h = area.h; - while (h--) { - SDL_memcpy(dst, src, w); - dst += w; - src += screen->pitch; - } - } - - /* Draw the mouse cursor */ - area.x -= SDL_cursor->area.x; - area.y -= SDL_cursor->area.y; - if ((area.x == 0) && (area.w == SDL_cursor->area.w)) { - SDL_DrawCursorFast(screen, &area); - } else { - SDL_DrawCursorSlow(screen, &area); - } -} - -void -SDL_DrawCursor(SDL_Surface * screen) -{ - /* Lock the screen if necessary */ - if (screen == NULL) { - return; - } - if (SDL_MUSTLOCK(screen)) { - if (SDL_LockSurface(screen) < 0) { - return; - } - } - - SDL_DrawCursorNoLock(screen); - - /* Unlock the screen and update if necessary */ - if (SDL_MUSTLOCK(screen)) { - SDL_UnlockSurface(screen); - } - if ((screen->flags & SDL_SCREEN_SURFACE) && - !(screen->flags & SDL_HWSURFACE)) { - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - SDL_Window *window; - SDL_Rect area; - - window = SDL_GetWindowFromSurface(screen); - if (!window) { - return; - } - - SDL_MouseRect(&area); - - if (_this->UpdateWindowSurface) { - _this->UpdateWindowSurface(_this, window, 1, &area); - } - } -} - -void -SDL_EraseCursorNoLock(SDL_Surface * screen) -{ - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - SDL_Window *window; - SDL_Rect area; - - /* Get the window associated with the surface */ - window = SDL_GetWindowFromSurface(screen); - if (!window || !window->surface) { - return; - } - - /* Get the mouse rectangle, clipped to the screen */ - SDL_MouseRect(&area); - if ((area.w == 0) || (area.h == 0)) { - return; - } - - /* Copy mouse background */ - { - int w, h, screenbpp; - Uint8 *src, *dst; - - /* Set up the copy pointers */ - screenbpp = screen->format->BytesPerPixel; - if ((screen->flags & SDL_SCREEN_SURFACE) || - FORMAT_EQUAL(screen->format, window->surface->format)) { - src = SDL_cursor->save[0]; - } else { - src = SDL_cursor->save[1]; - } - dst = (Uint8 *) screen->pixels + area.y * screen->pitch + - area.x * screenbpp; - - /* Perform the copy */ - w = area.w * screenbpp; - h = area.h; - while (h--) { - SDL_memcpy(dst, src, w); - src += w; - dst += screen->pitch; - } - - /* Perform pixel conversion on cursor background */ - if (src > SDL_cursor->save[1]) { - SDL_ConvertCursorSave(screen, area.w, area.h); - } - } -} - -void -SDL_EraseCursor(SDL_Surface * screen) -{ - /* Lock the screen if necessary */ - if (screen == NULL) { - return; - } - if (SDL_MUSTLOCK(screen)) { - if (SDL_LockSurface(screen) < 0) { - return; - } - } - - SDL_EraseCursorNoLock(screen); - - /* Unlock the screen and update if necessary */ - if (SDL_MUSTLOCK(screen)) { - SDL_UnlockSurface(screen); - } - if ((screen->flags & SDL_SCREEN_SURFACE) && - !(screen->flags & SDL_HWSURFACE)) { - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - SDL_Window *window; - SDL_Rect area; - - window = SDL_GetWindowFromSurface(screen); - if (!window) { - return; - } - - SDL_MouseRect(&area); - - if (_this->UpdateWindowSurface) { - _this->UpdateWindowSurface(_this, window, 1, &area); - } - } -} - -/* Reset the cursor on video mode change - FIXME: Keep track of all cursors, and reset them all. - */ -void -SDL_ResetCursor(void) -{ - int savelen; - - if (SDL_cursor) { - savelen = SDL_cursor->area.w * 4 * SDL_cursor->area.h; - SDL_cursor->area.x = 0; - SDL_cursor->area.y = 0; - SDL_memset(SDL_cursor->save[0], 0, savelen); + _this->WarpWMCursor(_this, windowID, x, y); } } diff --git a/src/video/SDL_cursor_c.h b/src/video/SDL_cursor_c.h index 0b994ff48..fa7498ec1 100644 --- a/src/video/SDL_cursor_c.h +++ b/src/video/SDL_cursor_c.h @@ -24,51 +24,12 @@ /* Useful variables and functions from SDL_cursor.c */ #include "SDL_mouse.h" -extern int SDL_CursorInit(Uint32 flags); -extern void SDL_CursorPaletteChanged(void); -extern void SDL_DrawCursor(SDL_Surface * screen); -extern void SDL_DrawCursorNoLock(SDL_Surface * screen); -extern void SDL_EraseCursor(SDL_Surface * screen); -extern void SDL_EraseCursorNoLock(SDL_Surface * screen); -extern void SDL_UpdateCursor(SDL_Surface * screen); -extern void SDL_ResetCursor(void); -extern void SDL_MoveCursor(int x, int y); +extern int SDL_CursorInit(void); extern void SDL_CursorQuit(void); -#define INLINE_MOUSELOCK -#ifdef INLINE_MOUSELOCK -/* Inline (macro) versions of the mouse lock functions */ -#include "SDL_mutex.h" - -extern SDL_mutex *SDL_cursorlock; - -#define SDL_LockCursor() \ - do { \ - if ( SDL_cursorlock ) { \ - SDL_mutexP(SDL_cursorlock); \ - } \ - } while ( 0 ) -#define SDL_UnlockCursor() \ - do { \ - if ( SDL_cursorlock ) { \ - SDL_mutexV(SDL_cursorlock); \ - } \ - } while ( 0 ) -#else -extern void SDL_LockCursor(void); -extern void SDL_UnlockCursor(void); -#endif /* INLINE_MOUSELOCK */ - -/* Only for low-level mouse cursor drawing */ -extern SDL_Cursor *SDL_cursor; -extern void SDL_MouseRect(SDL_Rect * area); - /* State definitions for the SDL cursor */ #define CURSOR_VISIBLE 0x01 -#define CURSOR_USINGSW 0x10 -#define SHOULD_DRAWCURSOR(X) \ - (((X)&(CURSOR_VISIBLE|CURSOR_USINGSW)) == \ - (CURSOR_VISIBLE|CURSOR_USINGSW)) extern volatile int SDL_cursorstate; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c index 23ecd6112..6d673d7e7 100644 --- a/src/video/SDL_pixels.c +++ b/src/video/SDL_pixels.c @@ -480,10 +480,10 @@ SDL_DitherColors(SDL_Color * colors, int bpp) /* * Calculate the pad-aligned scanline width of a surface */ -Uint16 +int SDL_CalculatePitch(SDL_Surface * surface) { - Uint16 pitch; + int pitch; /* Surface should be 4-byte aligned for speed */ pitch = surface->w * surface->format->BytesPerPixel; diff --git a/src/video/SDL_pixels_c.h b/src/video/SDL_pixels_c.h index 21490e78c..53a63537e 100644 --- a/src/video/SDL_pixels_c.h +++ b/src/video/SDL_pixels_c.h @@ -42,7 +42,7 @@ extern int SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst); extern void SDL_FreeBlitMap(SDL_BlitMap * map); /* Miscellaneous functions */ -extern Uint16 SDL_CalculatePitch(SDL_Surface * surface); +extern int SDL_CalculatePitch(SDL_Surface * surface); extern void SDL_DitherColors(SDL_Color * colors, int bpp); extern Uint8 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b); extern void SDL_ApplyGamma(Uint16 * gamma, SDL_Color * colors, diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index b974e8baa..6f0a237b7 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -43,6 +43,7 @@ SDL_CreateRGBSurface(Uint32 flags, SDL_Surface *screen; SDL_Surface *surface; + /* FIXME!! */ /* Make sure the size requested doesn't overflow our datatypes */ /* Next time I write a library like SDL, I'll use int for size. :) */ if (width >= 16384 || height >= 65536) { @@ -50,52 +51,13 @@ SDL_CreateRGBSurface(Uint32 flags, return (NULL); } - /* Check to see if we desire the surface in video memory */ - if (_this) { - screen = SDL_PublicSurface; - } else { - screen = NULL; - } - if (screen && ((screen->flags & SDL_HWSURFACE) == SDL_HWSURFACE)) { - if ((flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA)) != 0) { - flags |= SDL_HWSURFACE; - } - if ((flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { - if (!_this->info.blit_hw_CC) { - flags &= ~SDL_HWSURFACE; - } - } - if ((flags & SDL_SRCALPHA) == SDL_SRCALPHA) { - if (!_this->info.blit_hw_A) { - flags &= ~SDL_HWSURFACE; - } - } - } else { - flags &= ~SDL_HWSURFACE; - } - /* Allocate the surface */ surface = (SDL_Surface *) SDL_malloc(sizeof(*surface)); if (surface == NULL) { SDL_OutOfMemory(); return (NULL); } - surface->flags = SDL_SWSURFACE; - if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE) { - if ((Amask) && (_this->displayformatalphapixel)) { - depth = _this->displayformatalphapixel->BitsPerPixel; - Rmask = _this->displayformatalphapixel->Rmask; - Gmask = _this->displayformatalphapixel->Gmask; - Bmask = _this->displayformatalphapixel->Bmask; - Amask = _this->displayformatalphapixel->Amask; - } else { - depth = screen->format->BitsPerPixel; - Rmask = screen->format->Rmask; - Gmask = screen->format->Gmask; - Bmask = screen->format->Bmask; - Amask = screen->format->Amask; - } - } + surface->flags = 0; surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask); if (surface->format == NULL) { SDL_free(surface); @@ -108,27 +70,22 @@ SDL_CreateRGBSurface(Uint32 flags, surface->h = height; surface->pitch = SDL_CalculatePitch(surface); surface->pixels = NULL; - surface->offset = 0; surface->hwdata = NULL; surface->locked = 0; surface->map = NULL; - surface->unused1 = 0; SDL_SetClipRect(surface, NULL); SDL_FormatChanged(surface); /* Get the pixels */ - if (((flags & SDL_HWSURFACE) == SDL_SWSURFACE) || - (_this->AllocHWSurface(_this, surface) < 0)) { - if (surface->w && surface->h) { - surface->pixels = SDL_malloc(surface->h * surface->pitch); - if (surface->pixels == NULL) { - SDL_FreeSurface(surface); - SDL_OutOfMemory(); - return (NULL); - } - /* This is important for bitmaps */ - SDL_memset(surface->pixels, 0, surface->h * surface->pitch); + if (surface->w && surface->h) { + surface->pixels = SDL_malloc(surface->h * surface->pitch); + if (surface->pixels == NULL) { + SDL_FreeSurface(surface); + SDL_OutOfMemory(); + return NULL; } + /* This is important for bitmaps */ + SDL_memset(surface->pixels, 0, surface->h * surface->pitch); } /* Allocate an empty mapping */ @@ -167,7 +124,72 @@ SDL_CreateRGBSurfaceFrom(void *pixels, surface->pitch = pitch; SDL_SetClipRect(surface, NULL); } - return (surface); + return surface; +} + +SDL_Surface * +SDL_CreateRGBSurfaceFromTexture(SDL_TextureID textureID) +{ + SDL_Surface *surface; + Uint32 format; + int w, h; + int bpp; + Uint32 Rmask, Gmask, Bmask, Amask; + + if (SDL_QueryTexture(textureID, &format, NULL, &w, &h) < 0) { + return NULL; + } + + if (!SDL_PixelFormatEnumToMasks + (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { + SDL_SetError("Unknown texture format"); + return NULL; + } + + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, bpp, + Rmask, Gmask, Bmask, Amask); + if (surface != NULL) { + surface->flags |= (SDL_HWSURFACE | SDL_PREALLOC); + surface->w = width; + surface->h = height; + SDL_SetClipRect(surface, NULL); + } + return surface; +} + +/* + * Set the palette in a blittable surface + */ +int +SDL_SetColors(SDL_Surface * surface, SDL_Color * colors, int firstcolor, + int ncolors) +{ + SDL_Palette *pal; + int gotall; + int palsize; + + /* Verify the parameters */ + pal = surface->format->palette; + if (!pal) { + return 0; /* not a palettized surface */ + } + gotall = 1; + palsize = 1 << surface->format->BitsPerPixel; + if (ncolors > (palsize - firstcolor)) { + ncolors = (palsize - firstcolor); + gotall = 0; + } + + if (colors != (pal->colors + firstcolor)) { + SDL_memcpy(pal->colors + firstcolor, colors, + ncolors * sizeof(*colors)); + } + SDL_FormatChanged(surface); + + if (surface->flags & (SDL_SHADOW_SURFACE | SDL_SCREEN_SURFACE)) { + gotall &= SDL_SetScreenColors(surface, colors, firstcolor, ncolors); + } + return gotall; } /* diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 34ee4d7de..6ce7098ac 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -39,9 +39,71 @@ /* The SDL video driver */ -/* Define the SDL window structure, corresponding to toplevel windows */ typedef struct SDL_Window SDL_Window; +typedef struct SDL_Texture SDL_Texture; +typedef struct SDL_Renderer SDL_Renderer; +typedef struct SDL_RenderDriver SDL_RenderDriver; +typedef struct SDL_VideoDisplay SDL_VideoDisplay; +typedef struct SDL_VideoDevice SDL_VideoDevice; + +/* Define the SDL texture structure */ +struct SDL_Texture +{ + Uint32 id; + + Uint32 format; /**< The pixel format of the texture */ + int access; /**< SDL_TextureAccess */ + int w; /**< The width of the texture */ + int h; /**< The height of the texture */ + + SDL_Renderer *renderer; + + void *driverdata; /**< Driver specific texture representation */ + + SDL_Texture *next; +}; + +/* Define the SDL renderer structure */ +struct SDL_Renderer +{ + int (*CreateTexture) (SDL_Texture * texture); + int (*UpdateTexture) (SDL_Texture * texture, SDL_Rect * rect, + const void *pixels, int pitch); + int (*LockTexture) (SDL_Texture * texture, SDL_Rect * rect, int markDirty, + void **pixels, int *pitch); + void (*UnlockTexture) (SDL_Texture * texture); + void (*DirtyTexture) (SDL_Texture * texture, int numrects, + SDL_Rect * rects); + void (*SelectRenderTexture) (SDL_Texture * texture); + void (*RenderFill) (SDL_Rect * rect, Uint32 color); + int (*RenderCopy) (SDL_Texture * texture, SDL_Rect * srcrect, + SDL_Rect * dstrect, int blendMode, int scaleMode); + int (*RenderReadPixels) (SDL_Rect * rect, void *pixels, int pitch); + int (*RenderWritePixels) (SDL_Rect * rect, const void *pixels, int pitch); + void (*RenderPresent) (void); + void (*DestroyTexture) (SDL_Texture * texture); + + void (*DestroyRenderer) (SDL_Renderer * renderer); + + /* The current renderer info */ + SDL_RendererInfo info; + + /* The window associated with the renderer */ + SDL_Window *window; + void *driverdata; +}; + +/* Define the SDL render driver structure */ +struct SDL_RenderDriver +{ + SDL_Renderer *(*CreateRenderer) (SDL_Window * window, Uint32 flags); + + /* Info about the renderer capabilities */ + SDL_RendererInfo info; +}; + +/* Define the SDL window structure, corresponding to toplevel windows */ struct SDL_Window { Uint32 id; @@ -51,10 +113,10 @@ struct SDL_Window int w, h; Uint32 flags; - SDL_Surface *surface; - SDL_Surface *shadow; Uint16 *gamma; + SDL_Renderer *renderer; + void *userdata; void *driverdata; }; @@ -62,21 +124,26 @@ struct SDL_Window /* Define the SDL display structure This corresponds to physical monitors attached to the system. */ -typedef struct SDL_VideoDisplay +struct SDL_VideoDisplay { int num_display_modes; SDL_DisplayMode *display_modes; SDL_DisplayMode desktop_mode; SDL_DisplayMode current_mode; - int max_windows; + int num_render_drivers; + SDL_RenderDriver *render_drivers; + int num_windows; SDL_Window *windows; - void *driverdata; -} SDL_VideoDisplay; + SDL_Renderer *current_renderer; -typedef struct SDL_VideoDevice SDL_VideoDevice; + /* The hash list of textures */ + SDL_Texture *textures[64]; + + void *driverdata; +}; /* Define the SDL video driver structure */ #define _THIS SDL_VideoDevice *_this @@ -105,6 +172,13 @@ struct SDL_VideoDevice */ int (*SetDisplayMode) (_THIS, const SDL_DisplayMode * mode); + /* Sets the color entries { firstcolor .. (firstcolor+ncolors-1) } + of the physical palette to those in 'colors'. The return value + is 0 if all entries could be set properly or -1 otherwise. + */ + int (*SetDisplayColors) (_THIS, int firstcolor, int ncolors, + SDL_Color * colors); + /* * * */ /* Window functions */ @@ -122,22 +196,6 @@ struct SDL_VideoDevice void (*SetWindowGrab) (_THIS, SDL_Window * window); void (*DestroyWindow) (_THIS, SDL_Window * window); - void (*CreateWindowSurface) (_THIS, SDL_Window * window, Uint32 flags); - void (*UpdateWindowSurface) (_THIS, SDL_Window * window, int numrects, - SDL_Rect * rects); - void (*FlipWindowSurface) (_THIS, SDL_Window * window); - - /* Sets the color entries { firstcolor .. (firstcolor+ncolors-1) } - of the physical palette to those in 'colors'. If the device is - using a software palette (SDL_HWPALETTE not set), then the - changes are reflected in the logical palette of the screen - as well. - The return value is 1 if all entries could be set properly - or 0 otherwise. - */ - int (*SetWindowColors) (_THIS, SDL_Window * window, - int firstcolor, int ncolors, SDL_Color * colors); - /* Get some platform dependent window information */ SDL_bool(*GetWindowWMInfo) (_THIS, SDL_Window * window, SDL_SysWMinfo * info); @@ -157,9 +215,6 @@ struct SDL_VideoDevice /* * * */ /* Hardware acceleration functions */ - /* Information about the video hardware */ - SDL_VideoInfo info; - /* The pixel format used when SDL_CreateRGBSurface creates SDL_HWSURFACEs with alpha */ SDL_PixelFormat *displayformatalphapixel; @@ -242,23 +297,23 @@ struct SDL_VideoDevice /* Free a window manager cursor This function can be NULL if CreateWMCursor is also NULL. */ - void (*FreeWMCursor) (_THIS, WMcursor * cursor); + void (*FreeCursor) (_THIS, SDL_Cursor * cursor); /* If not NULL, create a black/white window manager cursor */ - WMcursor *(*CreateWMCursor) (_THIS, + SDL_Cursor *(*CreateCursor) (_THIS, Uint8 * data, Uint8 * mask, int w, int h, int hot_x, int hot_y); /* Show the specified cursor, or hide if cursor is NULL */ - int (*ShowWMCursor) (_THIS, WMcursor * cursor); + int (*ShowCursor) (_THIS, SDL_Cursor * cursor); /* Warp the window manager cursor to (x,y) If NULL, a mouse motion event is posted internally. */ - void (*WarpWMCursor) (_THIS, Uint16 x, Uint16 y); + void (*WarpCursor) (_THIS, SDL_WindowID windowID, int x, int y); /* If not NULL, this is called when a mouse motion event occurs */ - void (*MoveWMCursor) (_THIS, int x, int y); + void (*MoveCursor) (_THIS, int x, int y); /* Determine whether the mouse should be in relative mode or not. This function is called when the input grab state or cursor @@ -283,7 +338,7 @@ struct SDL_VideoDevice int num_displays; SDL_VideoDisplay *displays; int current_display; - Uint32 next_window_id; + Uint32 next_object_id; /* Driver information flags */ @@ -428,15 +483,14 @@ extern VideoBootStrap glSDL_bootstrap; #define SDL_CurrentDisplay (_this->displays[_this->current_display]) #define SDL_CurrentWindow (SDL_CurrentDisplay.windows[0]) -#define SDL_VideoSurface ((_this && SDL_CurrentDisplay.num_windows > 0) ? SDL_CurrentWindow.surface : NULL) -#define SDL_ShadowSurface ((_this && SDL_CurrentDisplay.num_windows > 0) ? SDL_CurrentWindow.shadow : NULL) -#define SDL_PublicSurface (SDL_ShadowSurface ? SDL_ShadowSurface : SDL_VideoSurface) extern SDL_VideoDevice *SDL_GetVideoDevice(); extern void SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode); extern void SDL_AddVideoDisplay(const SDL_VideoDisplay * display); -extern void SDL_AddDisplayMode(int display, const SDL_DisplayMode * mode); -extern SDL_Window *SDL_GetWindowFromSurface(SDL_Surface * surface); +extern void SDL_AddDisplayMode(int displayIndex, + const SDL_DisplayMode * mode); +extern void SDL_AddRenderDriver(int displayIndex, + const SDL_RenderDriver * driver); #endif /* _SDL_sysvideo_h */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 297477cbe..004aa4226 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -231,7 +231,7 @@ SDL_VideoInit(const char *driver_name, Uint32 flags) } _this = video; _this->name = bootstrap[i]->name; - _this->next_window_id = 1; + _this->next_object_id = 1; /* Set some very sane GL defaults */ @@ -268,16 +268,6 @@ SDL_VideoInit(const char *driver_name, Uint32 flags) return (-1); } - /* Temporarily here for backwards compatibility */ - { - int bpp; - Uint32 Rmask, Gmask, Bmask, Amask; - - SDL_PixelFormatEnumToMasks(SDL_GetDesktopDisplayMode()->format, &bpp, - &Rmask, &Gmask, &Bmask, &Amask); - _this->info.vfmt = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); - } - /* Sort the video modes */ for (i = 0; i < _this->num_displays; ++i) { SDL_qsort(_this->displays[i].display_modes, @@ -311,15 +301,6 @@ SDL_GetVideoDevice() return _this; } -const SDL_VideoInfo * -SDL_GetVideoInfo(void) -{ - if (!_this) { - return NULL; - } - return &_this->info; -} - void SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode) { @@ -330,7 +311,6 @@ SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode) display.desktop_mode = *desktop_mode; } display.current_mode = display.desktop_mode; - display.max_windows = 1; SDL_AddVideoDisplay(&display); } @@ -378,14 +358,15 @@ SDL_SelectVideoDisplay(int index) } void -SDL_AddDisplayMode(int display, const SDL_DisplayMode * mode) +SDL_AddDisplayMode(int displayIndex, const SDL_DisplayMode * mode) { + SDL_VideoDisplay *display = &_this->displays[displayIndex]; SDL_DisplayMode *modes; int i, nmodes; /* Make sure we don't already have the mode in the list */ - modes = SDL_CurrentDisplay.display_modes; - nmodes = SDL_CurrentDisplay.num_display_modes; + modes = display->display_modes; + nmodes = display->num_display_modes; for (i = 0; i < nmodes; ++i) { if (SDL_memcmp(mode, &modes[i], sizeof(*mode)) == 0) { return; @@ -395,9 +376,9 @@ SDL_AddDisplayMode(int display, const SDL_DisplayMode * mode) /* Go ahead and add the new mode */ modes = SDL_realloc(modes, (nmodes + 1) * sizeof(*mode)); if (modes) { - SDL_CurrentDisplay.display_modes = modes; + display->display_modes = modes; modes[nmodes] = *mode; - SDL_CurrentDisplay.num_display_modes++; + display->num_display_modes++; } } @@ -415,7 +396,7 @@ SDL_GetDisplayMode(int index) { if (index < 0 || index >= SDL_GetNumDisplayModes()) { SDL_SetError("index must be in the range of 0 - %d", - SDL_GetNumDisplayModes()); + SDL_GetNumDisplayModes() - 1); return NULL; } return &SDL_CurrentDisplay.display_modes[index]; @@ -568,19 +549,6 @@ SDL_SetDisplayMode(const SDL_DisplayMode * mode) return 0; } - /* Free any previous window surfaces */ - for (i = 0; i < display->num_windows; ++i) { - SDL_Window *window = &display->windows[i]; - if (window->shadow) { - SDL_FreeSurface(window->shadow); - window->shadow = NULL; - } - if (window->surface) { - SDL_FreeSurface(window->surface); - window->surface = NULL; - } - } - return _this->SetDisplayMode(_this, &display_mode); } @@ -605,7 +573,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) } SDL_zero(window); - window.id = _this->next_window_id++; + window.id = _this->next_object_id++; window.title = title ? SDL_strdup(title) : NULL; window.x = x; window.y = y; @@ -653,7 +621,7 @@ SDL_CreateWindowFrom(void *data) } SDL_zero(window); - window.id = _this->next_window_id++; + window.id = _this->next_object_id++; if (!_this->CreateWindowFrom || _this->CreateWindowFrom(_this, &window, data) < 0) { @@ -701,28 +669,6 @@ SDL_GetWindowFromID(SDL_WindowID windowID) return NULL; } -SDL_Window * -SDL_GetWindowFromSurface(SDL_Surface * surface) -{ - int i, j; - - if (!_this || !surface) { - return NULL; - } - - for (i = 0; i < _this->num_displays; ++i) { - SDL_VideoDisplay *display = &_this->displays[i]; - for (j = 0; j < display->num_windows; ++j) { - SDL_Window *window = &display->windows[j]; - if (surface == window->surface || surface == window->shadow) { - return window; - } - } - } - return NULL; -} - - Uint32 SDL_GetWindowFlags(SDL_WindowID windowID) { @@ -998,11 +944,8 @@ SDL_DestroyWindow(SDL_WindowID windowID) window->flags &= ~SDL_WINDOW_INPUT_GRABBED; _this->SetWindowGrab(_this, window); } - if (window->shadow) { - SDL_FreeSurface(window->shadow); - } - if (window->surface) { - SDL_FreeSurface(window->surface); + if (window->renderer) { + SDL_DestroyRenderer(window->id); } if (_this->DestroyWindow) { _this->DestroyWindow(_this, window); @@ -1024,371 +967,569 @@ SDL_DestroyWindow(SDL_WindowID windowID) } } -SDL_Surface * -SDL_CreateWindowSurface(SDL_WindowID windowID, Uint32 format, Uint32 flags) +void +SDL_AddRenderDriver(int displayIndex, const SDL_RenderDriver * driver) +{ + SDL_VideoDisplay *display = &_this->displays[displayIndex]; + SDL_RenderDriver *render_drivers; + + render_drivers = + SDL_realloc(display->render_drivers, + (display->num_render_drivers + + 1) * sizeof(*render_drivers)); + if (render_drivers) { + render_drivers[display->num_render_drivers] = *driver; + display->render_drivers = render_drivers; + display->num_render_drivers++; + } +} + +int +SDL_GetNumRenderers(void) +{ + if (_this) { + return SDL_CurrentDisplay.num_render_drivers; + } + return 0; +} + +int +SDL_GetRendererInfo(int index, SDL_RendererInfo * info) +{ + if (index < 0 || index >= SDL_GetNumRenderers()) { + SDL_SetError("index must be in the range of 0 - %d", + SDL_GetNumRenderers() - 1); + return -1; + } + *info = SDL_CurrentDisplay.render_drivers[index].info; + return 0; +} + +int +SDL_CreateRenderer(SDL_WindowID windowID, int index, Uint32 flags) { SDL_Window *window = SDL_GetWindowFromID(windowID); - Uint32 black; - SDL_Surface *surface; if (!window) { - return NULL; + return 0; } - if (!_this->CreateWindowSurface) { - return NULL; + if (index < 0) { + int n = SDL_GetNumRenderers(); + for (index = 0; index < n; ++index) { + if ((SDL_CurrentDisplay.render_drivers[index].info. + flags & flags) == flags) { + break; + } + } + if (index == n) { + SDL_SetError("Couldn't find matching render driver"); + return -1; + } + } + + if (index >= SDL_GetNumRenderers()) { + SDL_SetError("index must be -1 or in the range of 0 - %d", + SDL_GetNumRenderers() - 1); + return -1; } - if (!window->surface) { - _this->CreateWindowSurface(_this, window, flags); - if (!window->surface) { - return NULL; + /* Free any existing renderer */ + SDL_DestroyRenderer(windowID); + + /* Create a new renderer instance */ + window->renderer = + SDL_CurrentDisplay.render_drivers[index].CreateRenderer(window, + flags); + if (!window->renderer) { + return -1; + } + SDL_CurrentDisplay.current_renderer = window->renderer; + + return 0; +} + +int +SDL_SelectRenderer(SDL_WindowID windowID) +{ + SDL_Window *window = SDL_GetWindowFromID(windowID); + + if (!window || !window->renderer) { + return -1; + } + SDL_CurrentDisplay.current_renderer = window->renderer; + return 0; +} + +SDL_TextureID +SDL_CreateTexture(Uint32 format, int access, int w, int h) +{ + SDL_Renderer *renderer; + SDL_Texture *texture; + + if (!_this) { + return 0; + } + + renderer = SDL_CurrentDisplay.current_renderer; + if (!renderer || !renderer->CreateTexture) { + return 0; + } + + texture = (SDL_Texture *) SDL_malloc(sizeof(*texture)); + if (!texture) { + SDL_OutOfMemory(); + return 0; + } + + SDL_zerop(texture); + texture->id = _this->next_object_id++; + texture->format = format; + texture->access = access; + texture->w = w; + texture->h = h; + texture->renderer = renderer; + + if (renderer->CreateTexture(texture) < 0) { + SDL_free(texture); + return 0; + } +} + +SDL_TextureID +SDL_CreateTextureFromSurface(Uint32 format, int access, SDL_Surface * surface) +{ + SDL_TextureID textureID; + Uint32 surface_flags = surface->flags; + SDL_PixelFormat *fmt = surface->format; + Uint32 colorkey; + Uint8 alpha; + SDL_Rect bounds; + SDL_Surface dst; + int bpp; + Uint32 Rmask, Gmask, Bmask, Amask; + + if (!surface) { + SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface"); + return 0; + } + + if (format) { + if (!SDL_PixelFormatEnumToMasks + (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { + SDL_SetError("Unknown pixel format"); + return 0; } - window->surface->flags |= SDL_SCREEN_SURFACE; - - /* If we have a palettized surface, create a default palette */ - if (window->surface->format->palette) { - SDL_Color colors[256]; - SDL_PixelFormat *vf = window->surface->format; - SDL_DitherColors(colors, vf->BitsPerPixel); - SDL_SetColors(window->surface, colors, 0, vf->palette->ncolors); + } else { + bpp = fmt->BitsPerPixel; + Rmask = fmt->Rmask; + Gmask = fmt->Gmask; + Bmask = fmt->Bmask; + Amask = fmt->Amask; + format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask); + if (!format) { + SDL_SetError("Unknown pixel format"); + return 0; } } - surface = window->surface; - if (window->shadow) { - SDL_FreeSurface(window->shadow); - window->shadow = NULL; + textureID = SDL_CreateTexture(format, access, surface->w, surface->h); + if (!textureID) { + return 0; + } + + /* Set up a destination surface for the texture update */ + SDL_zero(dst); + dst.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); + if (!dst.format) { + SDL_DestroyTexture(textureID); + return 0; + } + dst.w = surface->w; + dst.h = surface->h; + if (SDL_LockTexture(textureID, NULL, 1, &dst.pixels, &dst.pitch) == 0) { + dst.flags |= SDL_PREALLOC; + } else { + dst.pitch = SDL_CalculatePitch(&dst); + dst.pixels = SDL_malloc(dst.h * dst.pitch); + if (!dst.pixels) { + SDL_DestroyTexture(textureID); + SDL_FreeFormat(dst.format); + SDL_OutOfMemory(); + return 0; + } } - /* Create a shadow surface if necessary */ - if ((!(flags & SDL_ANYFORMAT) - && (format != SDL_GetCurrentDisplayMode()->format)) - || ((flags & SDL_HWPALETTE) - && !(window->surface->flags & SDL_HWPALETTE))) { - int bpp; - Uint32 Rmask, Gmask, Bmask, Amask; + /* Copy the palette if any */ + if (fmt->palette && dst.format->palette) { + SDL_SetTexturePalette(textureID, fmt->palette->colors, 0, + fmt->palette->ncolors); + + SDL_memcpy(dst.format->palette->colors, + fmt->palette->colors, + fmt->palette->ncolors * sizeof(SDL_Color)); + dst.format->palette->ncolors = fmt->palette->ncolors; + } - SDL_PixelFormatEnumToMasks(format, &bpp, &Amask, &Gmask, &Bmask, - &Amask); - window->shadow = - SDL_CreateRGBSurface(SDL_SWSURFACE, surface->w, surface->h, bpp, - Rmask, Gmask, Bmask, Amask); - if (window->shadow == NULL) { - return NULL; + /* Make the texture transparent if the surface has colorkey */ + if (surface_flags & SDL_SRCCOLORKEY) { + int row; + int length = dst.w * dst.format->BytesPerPixel; + Uint8 *p = (Uint8 *) dst.pixels; + for (row = 0; row < dst.h; ++row) { + SDL_memset(p, 0, length); + p += dst.pitch; } - window->shadow->flags |= SDL_SHADOW_SURFACE; - - surface = window->shadow; - - /* 8-bit shadow surfaces report that they have exclusive palette */ - if (surface->format->palette) { - surface->flags |= SDL_HWPALETTE; - if (format == SDL_GetCurrentDisplayMode()->format) { - SDL_memcpy(surface->format->palette->colors, - window->surface->format->palette->colors, - window->surface->format->palette->ncolors * - sizeof(SDL_Color)); - } else { - SDL_DitherColors(surface->format->palette->colors, bpp); - } + } + + /* Copy over the alpha channel */ + if (surface_flags & SDL_SRCALPHA) { + if (fmt->Amask) { + surface->flags &= ~SDL_SRCALPHA; + } else { + /* FIXME: Need to make sure the texture has an alpha channel + * and copy 'alpha' into the texture alpha channel. + */ + alpha = surface->format->alpha; + SDL_SetAlpha(surface, 0, 0); } } - /* Clear the surface for display */ - { - Uint32 black = SDL_MapRGB(surface->format, 0, 0, 0); - SDL_FillRect(surface, NULL, black); - if (surface->flags & SDL_DOUBLEBUF) { - SDL_Flip(surface); - SDL_FillRect(surface, NULL, black); + /* Copy over the image data */ + bounds.x = 0; + bounds.y = 0; + bounds.w = surface->w; + bounds.h = surface->h; + SDL_LowerBlit(surface, &bounds, &dst, &bounds); + + /* Clean up the original surface */ + if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { + Uint32 cflags = surface_flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK); + SDL_SetColorKey(surface, cflags, colorkey); + } + if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) { + Uint32 aflags = surface_flags & (SDL_SRCALPHA | SDL_RLEACCELOK); + if (fmt->Amask) { + surface->flags |= SDL_SRCALPHA; + } else { + SDL_SetAlpha(surface, aflags, alpha); } - SDL_Flip(surface); } - return surface; -} + /* Update the texture */ + if (dst.flags & SDL_PREALLOC) { + SDL_UnlockTexture(textureID); + } else { + SDL_UpdateTexture(textureID, NULL, dst.pixels, dst.pitch); + SDL_free(dst.pixels); + } + SDL_FreeFormat(dst.format); -/* - * Convert a surface into the video pixel format. - */ -SDL_Surface * -SDL_DisplayFormat(SDL_Surface * surface) -{ - Uint32 flags; - - if (!SDL_PublicSurface) { - SDL_SetError("No video mode has been set"); - return (NULL); - } - /* Set the flags appropriate for copying to display surface */ - if (((SDL_PublicSurface->flags & SDL_HWSURFACE) == SDL_HWSURFACE) - && _this->info.blit_hw) - flags = SDL_HWSURFACE; - else - flags = SDL_SWSURFACE; -#ifdef AUTORLE_DISPLAYFORMAT - flags |= (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA)); - flags |= SDL_RLEACCELOK; -#else - flags |= - surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA | SDL_RLEACCELOK); -#endif - return (SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags)); + return textureID; } -/* - * Convert a surface into a format that's suitable for blitting to - * the screen, but including an alpha channel. - */ -SDL_Surface * -SDL_DisplayFormatAlpha(SDL_Surface * surface) -{ - SDL_PixelFormat *vf; - SDL_PixelFormat *format; - SDL_Surface *converted; - Uint32 flags; - /* default to ARGB8888 */ - Uint32 amask = 0xff000000; - Uint32 rmask = 0x00ff0000; - Uint32 gmask = 0x0000ff00; - Uint32 bmask = 0x000000ff; - - if (!SDL_PublicSurface) { - SDL_SetError("No video mode has been set"); - return (NULL); - } - vf = SDL_PublicSurface->format; - - switch (vf->BytesPerPixel) { - case 2: - /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}. - For anything else (like ARGB4444) it doesn't matter - since we have no special code for it anyway */ - if ((vf->Rmask == 0x1f) && - (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) { - rmask = 0xff; - bmask = 0xff0000; - } - break; +static __inline__ SDL_Texture * +SDL_GetTextureFromID(SDL_TextureID textureID) +{ + int hash; + SDL_Texture *texture; - case 3: - case 4: - /* Keep the video format, as long as the high 8 bits are - unused or alpha */ - if ((vf->Rmask == 0xff) && (vf->Bmask == 0xff0000)) { - rmask = 0xff; - bmask = 0xff0000; + if (!_this) { + return NULL; + } + + hash = (textureID % SDL_arraysize(SDL_CurrentDisplay.textures)); + for (texture = SDL_CurrentDisplay.textures[hash]; texture; + texture = texture->next) { + if (texture->id == textureID) { + return texture; } - break; + } + return NULL; +} - default: - /* We have no other optimised formats right now. When/if a new - optimised alpha format is written, add the converter here */ - break; +int +SDL_QueryTexture(SDL_TextureID textureID, Uint32 * format, int *access, + int *w, int *h) +{ + SDL_Texture *texture = SDL_GetTextureFromID(textureID); + + if (!texture) { + return -1; + } + + if (format) { + *format = texture->format; + } + if (access) { + *access = texture->access; } - format = SDL_AllocFormat(32, rmask, gmask, bmask, amask); - flags = SDL_PublicSurface->flags & SDL_HWSURFACE; - flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK); - converted = SDL_ConvertSurface(surface, format, flags); - SDL_FreeFormat(format); - return (converted); + if (w) { + *w = texture->w; + } + if (h) { + *h = texture->h; + } + return 0; +} + +int +SDL_UpdateTexture(SDL_TextureID textureID, SDL_Rect * rect, + const void *pixels, int pitch) +{ + SDL_Texture *texture = SDL_GetTextureFromID(textureID); + SDL_Renderer *renderer; + + if (!texture) { + return -1; + } + + renderer = texture->renderer; + if (!renderer->UpdateTexture) { + return -1; + } + return renderer->UpdateTexture(texture, rect, pixels, pitch); +} + +int +SDL_LockTexture(SDL_TextureID textureID, SDL_Rect * rect, int markDirty, + void **pixels, int *pitch) +{ + SDL_Texture *texture = SDL_GetTextureFromID(textureID); + SDL_Renderer *renderer; + + if (!texture) { + return -1; + } + + renderer = texture->renderer; + if (!renderer->LockTexture) { + return -1; + } + return renderer->LockTexture(texture, rect, markDirty, pixels, pitch); } -/* - * Update a specific portion of the physical screen - */ void -SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h) +SDL_UnlockTexture(SDL_TextureID textureID) { - if (screen) { - SDL_Rect rect; + SDL_Texture *texture = SDL_GetTextureFromID(textureID); + SDL_Renderer *renderer; - /* Perform some checking */ - if (w == 0) - w = screen->w; - if (h == 0) - h = screen->h; - if ((int) (x + w) > screen->w) - return; - if ((int) (y + h) > screen->h) - return; + if (!texture) { + return; + } - /* Fill the rectangle */ - rect.x = (Sint16) x; - rect.y = (Sint16) y; - rect.w = (Uint16) w; - rect.h = (Uint16) h; - SDL_UpdateRects(screen, 1, &rect); + renderer = texture->renderer; + if (!renderer->UnlockTexture) { + return; } + return renderer->UnlockTexture(texture); } + void -SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects) +SDL_DirtyTexture(SDL_TextureID textureID, int numrects, SDL_Rect * rects) { - int i; - SDL_Window *window; + SDL_Texture *texture = SDL_GetTextureFromID(textureID); + SDL_Renderer *renderer; - /* Find the window corresponding to this surface */ - window = SDL_GetWindowFromSurface(screen); - if (!window) { - SDL_SetError("Couldn't find window associated with surface"); + if (!texture) { return; } - if (screen->flags & SDL_SHADOW_SURFACE) { - if (SHOULD_DRAWCURSOR(SDL_cursorstate)) { - SDL_LockCursor(); - SDL_DrawCursor(screen); - for (i = 0; i < numrects; ++i) { - SDL_LowerBlit(screen, &rects[i], window->surface, &rects[i]); - } - SDL_EraseCursor(screen); - SDL_UnlockCursor(); - } else { - for (i = 0; i < numrects; ++i) { - SDL_LowerBlit(screen, &rects[i], window->surface, &rects[i]); - } - } + renderer = texture->renderer; + if (!renderer->DirtyTexture) { + return; + } + renderer->DirtyTexture(texture, numrects, rects); +} - /* Fall through to video surface update */ - screen = window->surface; - } - if ((screen->flags & SDL_SCREEN_SURFACE) && _this->UpdateWindowSurface) { - /* Update the video surface */ - if (screen->offset) { - int offset_y = screen->offset / screen->pitch; - int offset_x = screen->offset % screen->pitch; - for (i = 0; i < numrects; ++i) { - rects[i].x += offset_x; - rects[i].y += offset_y; - } - _this->UpdateWindowSurface(_this, window, numrects, rects); - for (i = 0; i < numrects; ++i) { - rects[i].x -= offset_x; - rects[i].y -= offset_y; - } - } else { - _this->UpdateWindowSurface(_this, window, numrects, rects); - } +void +SDL_SelectRenderTexture(SDL_TextureID textureID) +{ + SDL_Texture *texture = SDL_GetTextureFromID(textureID); + SDL_Renderer *renderer; + + if (!texture || texture->access != SDL_TextureAccess_Render) { + return; + } + renderer = texture->renderer; + if (!renderer->SelectRenderTexture) { + return; } + renderer->SelectRenderTexture(texture); } -/* - * Performs hardware double buffering, if possible, or a full update if not. - */ int -SDL_Flip(SDL_Surface * screen) +SDL_RenderFill(SDL_Rect * rect, Uint32 color) { - SDL_Window *window; + SDL_Renderer *renderer; - /* Find the window corresponding to this surface */ - window = SDL_GetWindowFromSurface(screen); - if (!window) { - SDL_SetError("Couldn't find window associated with surface"); + if (!_this) { + return -1; + } + + renderer = SDL_CurrentDisplay.current_renderer; + if (!renderer || !renderer->RenderFill) { + return -1; + } + + renderer->RenderFill(rect, color); +} + +int +SDL_RenderCopy(SDL_TextureID textureID, SDL_Rect * srcrect, + SDL_Rect * dstrect, int blendMode, int scaleMode) +{ + SDL_Texture *texture = SDL_GetTextureFromID(textureID); + SDL_Renderer *renderer; + + if (!texture || texture->renderer != SDL_CurrentDisplay.current_renderer) { return; } - /* Copy the shadow surface to the video surface */ - if (screen->flags & SDL_SHADOW_SURFACE) { - SDL_Rect rect; - - rect.x = 0; - rect.y = 0; - rect.w = screen->w; - rect.h = screen->h; - if (SHOULD_DRAWCURSOR(SDL_cursorstate)) { - SDL_LockCursor(); - SDL_DrawCursor(screen); - SDL_LowerBlit(screen, &rect, window->surface, &rect); - SDL_EraseCursor(screen); - SDL_UnlockCursor(); - } else { - SDL_LowerBlit(screen, &rect, window->surface, &rect); - } + renderer = SDL_CurrentDisplay.current_renderer; + if (!renderer || !renderer->RenderCopy) { + return -1; + } + + return renderer->RenderCopy(texture, srcrect, dstrect, blendMode, + scaleMode); +} - /* Fall through to video surface update */ - screen = window->surface; +int +SDL_RenderReadPixels(SDL_Rect * rect, void *pixels, int pitch) +{ + SDL_Renderer *renderer; + + if (!_this) { + return -1; } - if (screen->flags & SDL_DOUBLEBUF) { - _this->FlipWindowSurface(_this, window); - } else { - SDL_UpdateRect(screen, 0, 0, 0, 0); + + renderer = SDL_CurrentDisplay.current_renderer; + if (!renderer || !renderer->RenderReadPixels) { + return -1; } - return (0); + + return renderer->RenderReadPixels(rect, pixels, pitch); } int -SDL_SetColors(SDL_Surface * screen, SDL_Color * colors, int firstcolor, - int ncolors) +SDL_RenderWritePixels(SDL_Rect * rect, const void *pixels, int pitch) { - SDL_Window *window = NULL; - SDL_Palette *pal; - int gotall; - int palsize; + SDL_Renderer *renderer; - /* Verify the parameters */ - pal = screen->format->palette; - if (!pal) { - return 0; /* not a palettized surface */ + if (!_this) { + return -1; } - gotall = 1; - palsize = 1 << screen->format->BitsPerPixel; - if (ncolors > (palsize - firstcolor)) { - ncolors = (palsize - firstcolor); - gotall = 0; + + renderer = SDL_CurrentDisplay.current_renderer; + if (!renderer || !renderer->RenderWritePixels) { + return -1; } - if (colors != (pal->colors + firstcolor)) { - SDL_memcpy(pal->colors + firstcolor, colors, - ncolors * sizeof(*colors)); + return renderer->RenderWritePixels(rect, pixels, pitch); +} + +void +SDL_RenderPresent(void) +{ + SDL_Renderer *renderer; + + if (!_this) { + return; } - SDL_FormatChanged(screen); - if (screen->flags & (SDL_SHADOW_SURFACE | SDL_SCREEN_SURFACE)) { - window = SDL_GetWindowFromSurface(screen); - if (!window) { - return 0; - } + renderer = SDL_CurrentDisplay.current_renderer; + if (!renderer || !renderer->RenderPresent) { + return; } - if (screen->flags & SDL_SHADOW_SURFACE) { - SDL_Palette *vidpal; + renderer->RenderPresent(); +} + +void +SDL_DestroyTexture(SDL_TextureID textureID) +{ + int hash; + SDL_Texture *prev, *texture; + SDL_Renderer *renderer; - vidpal = window->surface->format->palette; - if (vidpal && vidpal->ncolors == pal->ncolors) { - /* This is a shadow surface, and the physical - * framebuffer is also indexed. Propagate the - * changes to its logical palette so that - * updates are always identity blits - */ - SDL_memcpy(vidpal->colors + firstcolor, colors, - ncolors * sizeof(*colors)); - } - if (window->surface->flags & SDL_HWPALETTE) { - /* Set the physical palette */ - screen = window->surface; - } else { - SDL_UpdateRect(screen, 0, 0, 0, 0); + if (!_this) { + return; + } + + /* Look up the texture in the hash table */ + hash = (textureID % SDL_arraysize(SDL_CurrentDisplay.textures)); + prev = NULL; + for (texture = SDL_CurrentDisplay.textures[hash]; texture; + prev = texture, texture = texture->next) { + if (texture->id == textureID) { + break; } } + if (!texture) { + return; + } + + /* Unlink the texture from the list */ + if (prev) { + prev->next = texture->next; + } else { + SDL_CurrentDisplay.textures[hash] = texture->next; + } + + /* Free the texture */ + renderer = texture->renderer; + renderer->DestroyTexture(texture); + SDL_free(texture); +} + +void +SDL_DestroyRenderer(SDL_WindowID windowID) +{ + SDL_Window *window = SDL_GetWindowFromID(windowID); + SDL_Renderer *renderer; + int i; + + if (!window) { + return; + } - if (screen->flags & SDL_SCREEN_SURFACE) { - if (_this->SetWindowColors) { - gotall = - _this->SetWindowColors(_this, window, firstcolor, ncolors, - colors); - if (!gotall) { - /* The video flags shouldn't have SDL_HWPALETTE, and - the video driver is responsible for copying back the - correct colors into the video surface palette. - */ - ; + renderer = window->renderer; + if (!renderer) { + return; + } + + /* Free existing textures for this renderer */ + for (i = 0; i < SDL_arraysize(SDL_CurrentDisplay.textures); ++i) { + SDL_Texture *texture; + SDL_Texture *prev = NULL; + SDL_Texture *next; + for (texture = SDL_CurrentDisplay.textures[i]; texture; + texture = next) { + next = texture->next; + if (texture->renderer == renderer) { + if (prev) { + prev->next = next; + } else { + SDL_CurrentDisplay.textures[i] = next; + } + renderer->DestroyTexture(texture); + SDL_free(texture); + } else { + prev = texture; } } - SDL_CursorPaletteChanged(); } - return gotall; + /* Free the renderer instance */ + renderer->DestroyRenderer(renderer); + + /* Clear references */ + window->renderer = NULL; + if (SDL_CurrentDisplay.current_renderer == renderer) { + SDL_CurrentDisplay.current_renderer = NULL; + } } void @@ -1416,12 +1557,12 @@ SDL_VideoQuit(void) SDL_free(display->windows); display->windows = NULL; } + SDL_free(display->info.vfmt); } _this->VideoQuit(_this); if (_this->displays) { SDL_free(_this->displays); } - SDL_free(_this->info.vfmt); _this->free(_this); _this = NULL; } @@ -1549,11 +1690,8 @@ SDL_GL_GetAttribute(SDL_GLattr attr, int *value) void SDL_GL_SwapBuffers(void) { - if (SDL_VideoSurface->flags & SDL_INTERNALOPENGL) { - _this->GL_SwapBuffers(_this); - } else { - SDL_SetError("OpenGL video mode has not been set"); - } + // FIXME: Track the current window context - do we provide N contexts, and match them to M windows, or is there a one-to-one mapping? + _this->GL_SwapBuffers(_this); } #if 0 // FIXME