1 /*	Public domain	*/
2 /*
3  * Generic graphics/input driver framework.
4  */
5 
6 #ifndef _AGAR_GUI_DRV_H_
7 #define _AGAR_GUI_DRV_H_
8 
9 #include <agar/gui/mouse.h>
10 #include <agar/gui/keyboard.h>
11 #include <agar/gui/keymap.h>
12 #include <agar/gui/surface.h>
13 
14 #include <agar/gui/begin.h>
15 
16 enum ag_driver_type {
17 	AG_FRAMEBUFFER,			/* Direct rendering to frame buffer */
18 	AG_VECTOR			/* Vector drawing */
19 };
20 enum ag_driver_wm_type {
21 	AG_WM_SINGLE,			/* Single display */
22 	AG_WM_MULTIPLE			/* Multiple windows */
23 };
24 
25 struct ag_widget;
26 struct ag_window;
27 struct ag_glyph;
28 struct ag_glyph_cache;
29 struct ag_cursor;
30 struct ag_driver_event;
31 
32 /* Generic graphics driver class */
33 typedef struct ag_driver_class {
34 	struct ag_object_class _inherit;
35 	const char *name;			/* Short name */
36 	enum ag_driver_type type;		/* Driver type */
37 	enum ag_driver_wm_type wm;		/* Window manager type */
38 	Uint flags;
39 #define AG_DRIVER_OPENGL	0x01		/* Supports OpenGL calls */
40 #define AG_DRIVER_SDL		0x02		/* Supports SDL calls */
41 #define AG_DRIVER_TEXTURES	0x04		/* Support texture ops */
42 
43 	/* Initialization */
44 	int  (*open)(void *drv, const char *spec);
45 	void (*close)(void *drv);
46 	int  (*getDisplaySize)(Uint *w, Uint *h);
47 	/* Event processing */
48 	void (*beginEventProcessing)(void *drv);
49 	int  (*pendingEvents)(void *drv);
50 	int  (*getNextEvent)(void *drv, struct ag_driver_event *dev);
51 	int  (*processEvent)(void *drv, struct ag_driver_event *dev);
52 	void (*genericEventLoop)(void *drv);
53 	void (*endEventProcessing)(void *drv);
54 	void (*terminate)(void);
55 	/* GUI rendering */
56 	void (*beginRendering)(void *drv);
57 	void (*renderWindow)(struct ag_window *);
58 	void (*endRendering)(void *drv);
59 	/* Primitives */
60 	void (*fillRect)(void *drv, AG_Rect r, AG_Color c);
61 	/* Update video region (rendering context; FB driver specific) */
62 	void (*updateRegion)(void *drv, AG_Rect r);
63 	/* Texture operations (GL driver specific) */
64 	void (*uploadTexture)(void *drv, Uint *, AG_Surface *, AG_TexCoord *);
65 	int  (*updateTexture)(void *drv, Uint, AG_Surface *, AG_TexCoord *);
66 	void (*deleteTexture)(void *drv, Uint);
67 	/* Request a specific refresh rate (driver specific) */
68 	int (*setRefreshRate)(void *drv, int fps);
69 	/* Clipping and blending control (rendering context) */
70 	void (*pushClipRect)(void *drv, AG_Rect r);
71 	void (*popClipRect)(void *drv);
72 	void (*pushBlendingMode)(void *drv, AG_BlendFn srcFn, AG_BlendFn dstFn);
73 	void (*popBlendingMode)(void *drv);
74 	/* Hardware cursor operations */
75 	struct ag_cursor *(*createCursor)(void *drv, Uint w, Uint h, const Uint8 *data, const Uint8 *mask, int xHot, int yHot);
76 	void (*freeCursor)(void *drv, struct ag_cursor *curs);
77 	int  (*setCursor)(void *drv, struct ag_cursor *curs);
78 	void (*unsetCursor)(void *drv);
79 	int  (*getCursorVisibility)(void *drv);
80 	void (*setCursorVisibility)(void *drv, int flag);
81 	/* Widget surface operations (rendering context) */
82 	void (*blitSurface)(void *drv, struct ag_widget *wid, AG_Surface *s, int x, int y);
83 	void (*blitSurfaceFrom)(void *drv, struct ag_widget *wid, struct ag_widget *widSrc, int s, AG_Rect *r, int x, int y);
84 	void (*blitSurfaceGL)(void *drv, struct ag_widget *wid, AG_Surface *s, float w, float h);
85 	void (*blitSurfaceFromGL)(void *drv, struct ag_widget *wid, int s, float w, float h);
86 	void (*blitSurfaceFlippedGL)(void *drv, struct ag_widget *wid, int s, float w, float h);
87 	void (*backupSurfaces)(void *drv, struct ag_widget *wid);
88 	void (*restoreSurfaces)(void *drv, struct ag_widget *wid);
89 	int  (*renderToSurface)(void *drv, struct ag_widget *wid, AG_Surface **su);
90 	/* Rendering operations (rendering context) */
91 	void (*putPixel)(void *drv, int x, int y, AG_Color c);
92 	void (*putPixel32)(void *drv, int x, int y, Uint32 c);
93 	void (*putPixelRGB)(void *drv, int x, int y, Uint8 r, Uint8 g, Uint8 b);
94 	void (*blendPixel)(void *drv, int x, int y, AG_Color c, AG_BlendFn fnSrc, AG_BlendFn fnDst);
95 	void (*drawLine)(void *drv, int x1, int y1, int x2, int y2, AG_Color C);
96 	void (*drawLineH)(void *drv, int x1, int x2, int y, AG_Color C);
97 	void (*drawLineV)(void *drv, int x, int y1, int y2, AG_Color C);
98 	void (*drawLineBlended)(void *drv, int x1, int y1, int x2, int y2, AG_Color C, AG_BlendFn fnSrc, AG_BlendFn fnDst);
99 	void (*drawArrowUp)(void *drv, int x0, int y0, int h, AG_Color C[2]);
100 	void (*drawArrowDown)(void *drv, int x0, int y0, int h, AG_Color C[2]);
101 	void (*drawArrowLeft)(void *drv, int x0, int y0, int h, AG_Color C[2]);
102 	void (*drawArrowRight)(void *drv, int x0, int y0, int h, AG_Color C[2]);
103 	void (*drawBoxRounded)(void *drv, AG_Rect r, int z, int rad, AG_Color C[3]);
104 	void (*drawBoxRoundedTop)(void *drv, AG_Rect r, int z, int rad, AG_Color C[3]);
105 	void (*drawCircle)(void *drv, int x, int y, int r, AG_Color C);
106 	void (*drawCircleFilled)(void *drv, int x, int y, int r, AG_Color C);
107 	void (*drawRectFilled)(void *drv, AG_Rect r, AG_Color C);
108 	void (*drawRectBlended)(void *drv, AG_Rect r, AG_Color C, AG_BlendFn fnSrc, AG_BlendFn fnDst);
109 	void (*drawRectDithered)(void *drv, AG_Rect r, AG_Color C);
110 	void (*updateGlyph)(void *drv, struct ag_glyph *);
111 	void (*drawGlyph)(void *drv, const struct ag_glyph *, int x, int y);
112 	/* Display list management (GL driver specific) */
113 	void (*deleteList)(void *drv, Uint);
114 } AG_DriverClass;
115 
116 /* Generic driver instance. */
117 typedef struct ag_driver {
118 	struct ag_object _inherit;
119 	Uint id;			/* Numerical instance ID */
120 	Uint flags;
121 #define AG_DRIVER_WINDOW_BG	0x02	/* Managed window background */
122 
123 	AG_Surface *sRef;		/* "Reference" surface */
124 	AG_PixelFormat *videoFmt;	/* Video pixel format (for
125 					   packed-pixel FB modes) */
126 	struct ag_keyboard *kbd;	/* Main keyboard device */
127 	struct ag_mouse *mouse;		/* Main mouse device */
128 	struct ag_cursor *activeCursor;	/* Effective cursor */
129 	AG_TAILQ_HEAD_(ag_cursor) cursors; /* Registered cursors */
130 	Uint                     nCursors;
131 	struct ag_glyph_cache *glyphCache; /* Cache of rendered glyphs */
132 	void *gl;			/* AG_GL_Context (for GL drivers) */
133 } AG_Driver;
134 
135 /* Generic driver event (for custom event loops). */
136 enum ag_driver_event_type {
137 	AG_DRIVER_UNKNOWN,		/* Unknown event */
138 	AG_DRIVER_MOUSE_MOTION,		/* Cursor moved */
139 	AG_DRIVER_MOUSE_BUTTON_DOWN,	/* Mouse button pressed */
140 	AG_DRIVER_MOUSE_BUTTON_UP,	/* Mouse button released */
141 	AG_DRIVER_MOUSE_ENTER,		/* Mouse entering window (MW) */
142 	AG_DRIVER_MOUSE_LEAVE,		/* Mouse leaving window (MW) */
143 	AG_DRIVER_FOCUS_IN,		/* Focus on window (MW) */
144 	AG_DRIVER_FOCUS_OUT,		/* Focus out of window (MW) */
145 	AG_DRIVER_KEY_DOWN,		/* Key pressed */
146 	AG_DRIVER_KEY_UP,		/* Key released */
147 	AG_DRIVER_EXPOSE,		/* Video update needed */
148 	AG_DRIVER_VIDEORESIZE,		/* Video resize request */
149 	AG_DRIVER_CLOSE			/* Window close request */
150 };
151 typedef struct ag_driver_event {
152 	enum ag_driver_event_type type;	/* Type of event */
153 	struct ag_window *win;		/* Associated window (AG_WM_MULTIPLE) */
154 	union {
155 		struct {
156 			int x, y;
157 		} motion;
158 		struct {
159 			AG_MouseButton which;
160 			int x, y;
161 		} button;
162 		struct {
163 			AG_KeySym ks;
164 			Uint32 ucs;
165 		} key;
166 		struct {
167 			int x, y, w, h;
168 		} videoresize;
169 	} data;
170 	AG_TAILQ_ENTRY(ag_driver_event) events;
171 } AG_DriverEvent;
172 
173 typedef AG_TAILQ_HEAD(ag_driver_eventq, ag_driver_event) AG_DriverEventQ;
174 
175 #define AGDRIVER(obj)		((AG_Driver *)(obj))
176 #define AGDRIVER_CLASS(obj)	((struct ag_driver_class *)(AGOBJECT(obj)->cls))
177 #define AGDRIVER_SINGLE(drv)	(AGDRIVER_CLASS(drv)->wm == AG_WM_SINGLE)
178 #define AGDRIVER_MULTIPLE(drv)	(AGDRIVER_CLASS(drv)->wm == AG_WM_MULTIPLE)
179 #define AGDRIVER_BOUNDED_WIDTH(win,x) (((x) < 0) ? 0 : \
180                                       ((x) > AGWIDGET(win)->w) ? (AGWIDGET(win)->w - 1) : (x))
181 #define AGDRIVER_BOUNDED_HEIGHT(win,y) (((y) < 0) ? 0 : \
182                                        ((y) > AGWIDGET(win)->h) ? (AGWIDGET(win)->h - 1) : (y))
183 __BEGIN_DECLS
184 extern AG_ObjectClass agDriverClass;
185 
186 extern AG_Object       agDrivers;	/* Drivers VFS */
187 extern AG_DriverClass *agDriverOps;	/* Current driver class */
188 extern void           *agDriverList[];	/* Available drivers (AG_DriverClass) */
189 extern Uint            agDriverListSize;
190 
191 #include <agar/config/have_clock_gettime.h>
192 #include <agar/config/have_pthreads.h>
193 #if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_PTHREADS)
194 extern AG_Cond agCondBeginRender;	/* For agTimeOps_render */
195 extern AG_Cond agCondEndRender;
196 #endif
197 
198 void       AG_ListDriverNames(char *, size_t)
199                               BOUNDED_ATTRIBUTE(__string__, 1, 2);
200 int        AG_DriverProbe(AG_DriverClass *, const char *);
201 AG_Driver *AG_DriverOpen(AG_DriverClass *);
202 void       AG_DriverClose(AG_Driver *);
203 void       AG_ViewCapture(void);
204 
205 /* Lookup a driver instance by ID */
206 static __inline__ AG_Driver *
AG_GetDriverByID(Uint id)207 AG_GetDriverByID(Uint id)
208 {
209 	AG_Driver *drv;
210 
211 	AGOBJECT_FOREACH_CHILD(drv, &agDrivers, ag_driver) {
212 		if (drv->id == id)
213 			return (drv);
214 	}
215 	return (NULL);
216 }
217 
218 /* Enter GUI rendering context. */
219 static __inline__ void
AG_BeginRendering(void * drv)220 AG_BeginRendering(void *drv)
221 {
222 #if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_PTHREADS)
223 	if (agTimeOps == &agTimeOps_renderer)		/* Renderer-aware ops */
224 		AG_CondBroadcast(&agCondBeginRender);
225 #endif
226 	agRenderingContext = 1;
227 	AGDRIVER_CLASS(drv)->beginRendering(drv);
228 }
229 
230 /* Leave GUI rendering context. */
231 static __inline__ void
AG_EndRendering(void * drv)232 AG_EndRendering(void *drv)
233 {
234 	AGDRIVER_CLASS(drv)->endRendering(drv);
235 	agRenderingContext = 0;
236 #if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_PTHREADS)
237 	if (agTimeOps == &agTimeOps_renderer)		/* Renderer-aware ops */
238 		AG_CondBroadcast(&agCondEndRender);
239 #endif
240 }
241 __END_DECLS
242 
243 #include <agar/gui/drv_mw.h>
244 #include <agar/gui/drv_sw.h>
245 
246 __BEGIN_DECLS
247 /* Return whether Agar is using OpenGL. */
248 static __inline__ int
AG_UsingGL(void * drv)249 AG_UsingGL(void *drv)
250 {
251 	if (drv != NULL) {
252 		return (AGDRIVER_CLASS(drv)->flags & AG_DRIVER_OPENGL);
253 	} else {
254 		return (agDriverOps->flags & AG_DRIVER_OPENGL);
255 	}
256 }
257 
258 /* Return whether Agar is using SDL. */
259 static __inline__ int
AG_UsingSDL(void * drv)260 AG_UsingSDL(void *drv)
261 {
262 	AG_DriverClass *dc = (drv != NULL) ? AGDRIVER_CLASS(drv) : agDriverOps;
263 	return (dc->flags & AG_DRIVER_SDL);
264 }
265 
266 /* Query a driver for available display area in pixels. */
267 static __inline__ int
AG_GetDisplaySize(void * drv,Uint * w,Uint * h)268 AG_GetDisplaySize(void *drv, Uint *w, Uint *h)
269 {
270 	AG_DriverClass *dc = (drv != NULL) ? AGDRIVER_CLASS(drv) : agDriverOps;
271 	AG_DriverSw *dsw = (drv != NULL) ? (AG_DriverSw *)drv : agDriverSw;
272 
273 	switch (dc->wm) {
274 	case AG_WM_SINGLE:
275 		*w = dsw->w;
276 		*h = dsw->h;
277 		return (0);
278 	case AG_WM_MULTIPLE:
279 		return dc->getDisplaySize(w, h);
280 	}
281 	return (-1);
282 }
283 __END_DECLS
284 
285 #include <agar/gui/close.h>
286 #endif /* _AGAR_GUI_DRV_H_ */
287