zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_rpimouse.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "SDL_config.h"
22 
23 #if SDL_VIDEO_DRIVER_RPI
24 
25 #include "SDL_assert.h"
26 #include "SDL_surface.h"
27 
28 #include "SDL_rpivideo.h"
29 #include "SDL_rpimouse.h"
30 
31 #include "../SDL_sysvideo.h"
32 #include "../../events/SDL_mouse_c.h"
33 #include "../../events/default_cursor.h"
34 
35 /* Copied from vc_vchi_dispmanx.h which is bugged and tries to include a non existing file */
36 /* Attributes changes flag mask */
37 #define ELEMENT_CHANGE_LAYER (1<<0)
38 #define ELEMENT_CHANGE_OPACITY (1<<1)
39 #define ELEMENT_CHANGE_DEST_RECT (1<<2)
40 #define ELEMENT_CHANGE_SRC_RECT (1<<3)
41 #define ELEMENT_CHANGE_MASK_RESOURCE (1<<4)
42 #define ELEMENT_CHANGE_TRANSFORM (1<<5)
43 /* End copied from vc_vchi_dispmanx.h */
44 
45 static SDL_Cursor *RPI_CreateDefaultCursor(void);
46 static SDL_Cursor *RPI_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y);
47 static int RPI_ShowCursor(SDL_Cursor * cursor);
48 static void RPI_MoveCursor(SDL_Cursor * cursor);
49 static void RPI_FreeCursor(SDL_Cursor * cursor);
50 static void RPI_WarpMouse(SDL_Window * window, int x, int y);
51 
52 static SDL_Cursor *
53 RPI_CreateDefaultCursor(void)
54 {
56 }
57 
58 /* Create a cursor from a surface */
59 static SDL_Cursor *
60 RPI_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
61 {
62  RPI_CursorData *curdata;
63  SDL_Cursor *cursor;
64  int ret;
65  VC_RECT_T dst_rect;
66  Uint32 dummy;
67 
69  SDL_assert(surface->pitch == surface->w * 4);
70 
71  cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor));
72  curdata = (RPI_CursorData *) SDL_calloc(1, sizeof(*curdata));
73 
74  curdata->hot_x = hot_x;
75  curdata->hot_y = hot_y;
76  curdata->w = surface->w;
77  curdata->h = surface->h;
78 
79  /* This usage is inspired by Wayland/Weston RPI code, how they figured this out is anyone's guess */
80  curdata->resource = vc_dispmanx_resource_create( VC_IMAGE_ARGB8888, surface->w | (surface->pitch << 16), surface->h | (surface->h << 16), &dummy );
81  SDL_assert(curdata->resource);
82  vc_dispmanx_rect_set( &dst_rect, 0, 0, curdata->w, curdata->h);
83  /* A note from Weston:
84  * vc_dispmanx_resource_write_data() ignores ifmt,
85  * rect.x, rect.width, and uses stride only for computing
86  * the size of the transfer as rect.height * stride.
87  * Therefore we can only write rows starting at x=0.
88  */
89  ret = vc_dispmanx_resource_write_data( curdata->resource, VC_IMAGE_ARGB8888, surface->pitch, surface->pixels, &dst_rect );
90  SDL_assert ( ret == DISPMANX_SUCCESS );
91 
92  cursor->driverdata = curdata;
93 
94  return cursor;
95 
96 }
97 
98 /* Show the specified cursor, or hide if cursor is NULL */
99 static int
100 RPI_ShowCursor(SDL_Cursor * cursor)
101 {
102  int ret;
103  DISPMANX_UPDATE_HANDLE_T update;
104  RPI_CursorData *curdata;
105  VC_RECT_T src_rect, dst_rect;
106  SDL_Mouse *mouse;
109  VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FROM_SOURCE /* flags */ , 255 /*opacity 0->255*/, 0 /* mask */ };
110 
111  mouse = SDL_GetMouse();
112  if (mouse == NULL) {
113  return -1;
114  }
115 
116  if (cursor == NULL) {
117  /* FIXME: We hide the current mouse's cursor, what we actually need is *_HideCursor */
118 
119  if ( mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) {
120  curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata;
121  if (curdata->element > DISPMANX_NO_HANDLE) {
122  update = vc_dispmanx_update_start( 10 );
123  SDL_assert( update );
124  ret = vc_dispmanx_element_remove( update, curdata->element );
125  SDL_assert( ret == DISPMANX_SUCCESS );
126  ret = vc_dispmanx_update_submit_sync( update );
127  SDL_assert( ret == DISPMANX_SUCCESS );
128  curdata->element = DISPMANX_NO_HANDLE;
129  }
130  }
131  return 0;
132  }
133 
134  curdata = (RPI_CursorData *) cursor->driverdata;
135  if (curdata == NULL) {
136  return -1;
137  }
138 
139  if (mouse->focus == NULL) {
140  return -1;
141  }
142 
143  display = SDL_GetDisplayForWindow(mouse->focus);
144  if (display == NULL) {
145  return -1;
146  }
147 
148  data = (SDL_DisplayData*) display->driverdata;
149  if (data == NULL) {
150  return -1;
151  }
152 
153  if (curdata->element == DISPMANX_NO_HANDLE) {
154  vc_dispmanx_rect_set( &src_rect, 0, 0, curdata->w << 16, curdata->h << 16 );
155  vc_dispmanx_rect_set( &dst_rect, 0, 0, curdata->w, curdata->h);
156 
157  update = vc_dispmanx_update_start( 10 );
158  SDL_assert( update );
159 
160  curdata->element = vc_dispmanx_element_add( update,
161  data->dispman_display,
162  SDL_RPI_MOUSELAYER, // layer
163  &dst_rect,
164  curdata->resource,
165  &src_rect,
166  DISPMANX_PROTECTION_NONE,
167  &alpha,
168  DISPMANX_NO_HANDLE, // clamp
169  VC_IMAGE_ROT0 );
170  SDL_assert( curdata->element > DISPMANX_NO_HANDLE);
171  ret = vc_dispmanx_update_submit_sync( update );
172  SDL_assert( ret == DISPMANX_SUCCESS );
173  }
174 
175  return 0;
176 }
177 
178 /* Free a window manager cursor */
179 static void
180 RPI_FreeCursor(SDL_Cursor * cursor)
181 {
182  int ret;
183  DISPMANX_UPDATE_HANDLE_T update;
184  RPI_CursorData *curdata;
185 
186  if (cursor != NULL) {
187  curdata = (RPI_CursorData *) cursor->driverdata;
188 
189  if (curdata != NULL) {
190  if (curdata->element != DISPMANX_NO_HANDLE) {
191  update = vc_dispmanx_update_start( 10 );
192  SDL_assert( update );
193  ret = vc_dispmanx_element_remove( update, curdata->element );
194  SDL_assert( ret == DISPMANX_SUCCESS );
195  ret = vc_dispmanx_update_submit_sync( update );
196  SDL_assert( ret == DISPMANX_SUCCESS );
197  }
198 
199  if (curdata->resource != DISPMANX_NO_HANDLE) {
200  ret = vc_dispmanx_resource_delete( curdata->resource );
201  SDL_assert( ret == DISPMANX_SUCCESS );
202  }
203 
204  SDL_free(cursor->driverdata);
205  }
206  SDL_free(cursor);
207  }
208 }
209 
210 /* Warp the mouse to (x,y) */
211 static void
212 RPI_WarpMouse(SDL_Window * window, int x, int y)
213 {
214  RPI_CursorData *curdata;
215  DISPMANX_UPDATE_HANDLE_T update;
216  int ret;
217  VC_RECT_T dst_rect;
218  SDL_Mouse *mouse = SDL_GetMouse();
219 
220  if (mouse != NULL && mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) {
221  curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata;
222  if (curdata->element != DISPMANX_NO_HANDLE) {
223  update = vc_dispmanx_update_start( 10 );
224  SDL_assert( update );
225  vc_dispmanx_rect_set( &dst_rect, x, y, curdata->w, curdata->h);
226  ret = vc_dispmanx_element_change_attributes(
227  update,
228  curdata->element,
229  ELEMENT_CHANGE_DEST_RECT,
230  0,
231  0,
232  &dst_rect,
233  NULL,
234  DISPMANX_NO_HANDLE,
235  DISPMANX_NO_ROTATE);
236  SDL_assert( ret == DISPMANX_SUCCESS );
237  /* Submit asynchronously, otherwise the peformance suffers a lot */
238  ret = vc_dispmanx_update_submit( update, 0, NULL );
239  SDL_assert( ret == DISPMANX_SUCCESS );
240  }
241  }
242 }
243 
244 void
246 {
247  /* FIXME: Using UDEV it should be possible to scan all mice
248  * but there's no point in doing so as there's no multimice support...yet!
249  */
250  SDL_Mouse *mouse = SDL_GetMouse();
251 
252  mouse->CreateCursor = RPI_CreateCursor;
253  mouse->ShowCursor = RPI_ShowCursor;
254  mouse->MoveCursor = RPI_MoveCursor;
255  mouse->FreeCursor = RPI_FreeCursor;
256  mouse->WarpMouse = RPI_WarpMouse;
257 
258  SDL_SetDefaultCursor(RPI_CreateDefaultCursor());
259 }
260 
261 void
263 {
264 
265 }
266 
267 /* This is called when a mouse motion event occurs */
268 static void
269 RPI_MoveCursor(SDL_Cursor * cursor)
270 {
271  SDL_Mouse *mouse = SDL_GetMouse();
272  RPI_WarpMouse(mouse->focus, mouse->x, mouse->y);
273 }
274 
275 #endif /* SDL_VIDEO_DRIVER_RPI */
276 
277 /* vi: set ts=4 sw=4 expandtab: */
#define DEFAULT_CWIDTH
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:62
DECLSPEC SDL_Cursor *SDLCALL SDL_CreateCursor(const Uint8 *data, const Uint8 *mask, int w, int h, int hot_x, int hot_y)
Create a cursor, using the specified bitmap data and mask (in MSB format).
Definition: SDL_mouse.c:486
DECLSPEC void *SDLCALL SDL_calloc(size_t nmemb, size_t size)
#define NULL
Definition: ftobjs.h:61
#define SDL_RPI_MOUSELAYER
Definition: SDL_rpivideo.h:54
SDL_Window * focus
Definition: SDL_mouse_c.h:61
EGLSurface EGLint x
Definition: eglext.h:293
EGLSurface surface
Definition: eglext.h:74
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
DECLSPEC void SDLCALL SDL_free(void *mem)
#define DEFAULT_CHOTY
char * display
Definition: visualinfo.c:85
if(!yyg->yy_init)
#define DEFAULT_CHOTX
ret
Definition: glew_str_glx.c:2
DISPMANX_ELEMENT_HANDLE_T element
Definition: SDL_rpimouse.h:31
void(* MoveCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:48
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:145
void(* FreeCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:51
SDL_Cursor *(* CreateCursor)(SDL_Surface *surface, int hot_x, int hot_y)
Definition: SDL_mouse_c.h:39
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
void * pixels
Definition: SDL_surface.h:75
#define _THIS
int(* ShowCursor)(SDL_Cursor *cursor)
Definition: SDL_mouse_c.h:45
DISPMANX_RESOURCE_HANDLE_T resource
Definition: SDL_rpimouse.h:30
DISPMANX_DISPLAY_HANDLE_T dispman_display
Definition: SDL_rpivideo.h:41
#define DEFAULT_CHEIGHT
GLclampf GLclampf GLclampf alpha
Definition: glew.h:1506
void SDL_SetDefaultCursor(SDL_Cursor *cursor)
Definition: SDL_mouse.c:51
#define SDL_assert(condition)
Definition: SDL_assert.h:159
EGLSurface EGLint EGLint y
Definition: eglext.h:293
SDL_PixelFormat * format
Definition: SDL_surface.h:72
static const unsigned char default_cmask[]
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:996
void RPI_QuitMouse(_THIS)
static const unsigned char default_cdata[]
SDL_Cursor * cur_cursor
Definition: SDL_mouse_c.h:74
void * driverdata
Definition: SDL_mouse_c.h:33
void RPI_InitMouse(_THIS)
void(* WarpMouse)(SDL_Window *window, int x, int y)
Definition: SDL_mouse_c.h:54