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