PageRenderTime 42ms CodeModel.GetById 12ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/opengles/ug/ug_ftk.c

http://ftk.googlecode.com/
C | 363 lines | 271 code | 68 blank | 24 comment | 35 complexity | 047471964e79160d37f7602d1eee6ca0 MD5 | raw file
  1/*
  2 * GLESonGL implementation
  3 * Version:  1.2
  4 *
  5 * Copyright (C) 2003  David Blythe   All Rights Reserved.
  6 * Copyright (C) 2010  Li XianJing	 All Rights Reserved.
  7 *
  8 * Permission is hereby granted, free of charge, to any person obtaining a
  9 * copy of this software and associated documentation files (the "Software"),
 10 * to deal in the Software without restriction, including without limitation
 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 12 * and/or sell copies of the Software, and to permit persons to whom the
 13 * Software is furnished to do so, subject to the following conditions:
 14 *
 15 * The above copyright notice and this permission notice shall be included
 16 * in all copies or substantial portions of the Software.
 17 *
 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 21 * DAVID BLYTHE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 24 */
 25
 26#include <stdlib.h>
 27#include <string.h>
 28#include <stdio.h>
 29#include <ftk.h>
 30#include <GLES/egl.h>
 31#include "ug.h"
 32
 33typedef struct {
 34	EGLDisplay egldpy;
 35	NativeDisplayType dpy;
 36	struct ugwindow* win, * winlist;
 37} UGCtx_t;
 38
 39static UGCtx_t* context = NULL;
 40
 41typedef void (*uGIdle)(UGWindow w);
 42typedef void (*uGDraw)(UGWindow w);
 43typedef void (*uGMotion)(UGWindow w, int x, int y);
 44typedef void (*uGKbd)(UGWindow w, int key, int x, int y);
 45typedef void (*uGPointer)(UGWindow w, int button, int state, int x, int y);
 46typedef void (*uGReshape)(UGWindow w, int width,int height);
 47typedef EGLBoolean (*PFNSAVESURFACE)(EGLSurface surface, const char* filename);
 48
 49typedef struct ugwindow {
 50	int width;
 51	int height;
 52	int redraw;
 53	UGCtx_t* ug;
 54	FtkWidget* win;
 55   
 56	int x;
 57	int y;
 58	uGKbd kbd;
 59	uGDraw draw;
 60	uGMotion motion;
 61	uGReshape reshape;
 62	uGPointer pointer;
 63	
 64	EGLContext eglctx;
 65	EGLSurface surface;
 66	EGLConfig  eglconfig;
 67	FtkSource* painter_idle;
 68	struct ugwindow* next, * prev;
 69} UGWindow_t;
 70
 71static int argc = 1;
 72static int ug_user_ref = 0;
 73static char* argv[] = {"gles", NULL};
 74static PFNSAVESURFACE pfnSaveSurface;	 // function pointer used to save images 
 75
 76UGCtx APIENTRY ugInit(void) 
 77{
 78	UGCtx_t* ug = NULL;
 79	
 80	ug_user_ref++;
 81	if(ug_user_ref > 1)
 82	{
 83		return context;
 84	}
 85
 86	ug = calloc(1, sizeof *ug);
 87	return_val_if_fail(ug != NULL, 0);
 88
 89	ftk_init(argc, argv);
 90	ug->dpy = ftk_default_display();
 91	ug->egldpy = eglGetDisplay(ug->dpy);
 92
 93	context = ug;
 94	eglInitialize(ug->egldpy, NULL, NULL);
 95	pfnSaveSurface = (PFNSAVESURFACE)eglGetProcAddress("eglSaveSurfaceHM");
 96
 97	return (UGCtx)ug;
 98}
 99
100void APIENTRY
101ugFini(UGCtx ug) {
102	UGCtx_t* _ug = (UGCtx_t*)ug;
103
104	ug_user_ref--;
105	if(ug_user_ref == 0)
106	{
107		eglTerminate(_ug->egldpy);
108		free(_ug);
109		context = NULL;
110	}
111}
112
113UGCtx APIENTRY ugCtxFromWin(UGWindow uwin) {
114	return (UGCtx)((UGWindow_t*)uwin)->ug;
115}
116
117static void
118bind_context(UGCtx_t* ug, UGWindow_t* w) {
119	if (!eglMakeCurrent(ug->egldpy, w->surface, w->surface, w->eglctx)) {
120		printf("botch makecurrent\n");
121		exit(1);
122	}
123	ug->win = w;
124}
125
126static int GetKey(int vk) 
127{
128	switch (vk) {
129	case FTK_KEY_F1:			return UG_KEY_F1;
130	case FTK_KEY_F2:			return UG_KEY_F2;
131	case FTK_KEY_F3:			return UG_KEY_F3;
132	case FTK_KEY_F4:			return UG_KEY_F4;
133	case FTK_KEY_F5:			return UG_KEY_F5;
134	case FTK_KEY_F6:			return UG_KEY_F6;
135	case FTK_KEY_F7:			return UG_KEY_F7;
136	case FTK_KEY_F8:			return UG_KEY_F8;
137	case FTK_KEY_F9:			return UG_KEY_F9;
138	case FTK_KEY_F10:		return UG_KEY_F10;
139	case FTK_KEY_LEFT:		return UG_KEY_LEFT;
140	case FTK_KEY_UP:			return UG_KEY_UP;
141	case FTK_KEY_RIGHT:		return UG_KEY_RIGHT;
142	case FTK_KEY_DOWN:		return UG_KEY_DOWN;
143	case FTK_KEY_PRIOR:		return UG_KEY_PAGE_UP;
144	case FTK_KEY_NEXT:		return UG_KEY_PAGE_DOWN;
145	case FTK_KEY_HOME:		return UG_KEY_HOME;
146	case FTK_KEY_END:		return UG_KEY_END;
147	case FTK_KEY_INSERT:		return UG_KEY_INSERT;
148	default:			return vk;
149	}
150}
151
152
153static Ret	ug_win_on_event(void* user_data, void* obj)
154{
155	FtkEvent* event = obj;
156	UGWindow_t* win = user_data;
157
158	switch(event->type)
159	{
160		case FTK_EVT_KEY_DOWN:
161		{
162			int key = GetKey(event->u.key.code);
163
164			if(win->kbd != NULL)
165			{
166				win->kbd((UGWindow)win, key, win->x, win->y); 
167			}
168			break;
169		}
170		case FTK_EVT_MOUSE_UP:
171		case FTK_EVT_MOUSE_DOWN:
172		{
173			if(win->pointer != NULL)
174			{
175				int state = event->type == FTK_EVT_MOUSE_DOWN ? UG_BUT_DOWN : UG_BUT_UP;
176				win->pointer((UGWindow)win, UG_BUT_LEFT, state, event->u.mouse.x, event->u.mouse.y);
177			}
178
179			break;
180		}
181		case FTK_EVT_MOUSE_MOVE:
182		{
183			if(win->motion != NULL)
184			{
185				win->motion((UGWindow)win, event->u.mouse.x, event->u.mouse.y);
186			}
187			break;
188		}
189		default:
190		{
191			return RET_OK;
192		}
193	}
194
195	return RET_REMOVE;
196}
197
198static int attribs[] = { EGL_RED_SIZE, 1, EGL_NONE }; /*XXXblythe*/
199static int attribs2[] = {EGL_RED_SIZE, 1, EGL_DEPTH_SIZE, 1, EGL_NONE};
200
201UGWindow APIENTRY ugCreateWindow(UGCtx ug,	const char* config, 
202	const char* title, int width, int height, int x, int y) {
203	
204	EGLint n, vid;
205	EGLConfig configs[1];
206	UGCtx_t* _ug = (UGCtx_t*)ug;
207	UGWindow_t *w = calloc(1, sizeof *w);
208	int depth = strstr(config, "UG_DEPTH") != 0;
209
210	return_val_if_fail(ug != 0 && w != NULL, 0);
211
212	w->ug = _ug;
213	if (!eglChooseConfig(_ug->egldpy, depth ? attribs2 : attribs, configs, 1, &n)) 
214	{
215		free(w);
216		return 0;
217	}
218	
219	w->eglconfig = configs[0];
220	eglGetConfigAttrib(_ug->egldpy, configs[0], EGL_NATIVE_VISUAL_ID, &vid);
221	
222	w->win = ftk_app_window_create();
223	ftk_window_set_animation_hint(w->win, "app_main_window");
224	return_val_if_fail(w->win != NULL, 0);
225
226	ftk_widget_set_text(w->win, title);
227	ftk_widget_set_event_listener(w->win, ug_win_on_event, w);
228	ftk_widget_show(w->win, 1);
229	ftk_widget_set_user_data(w->win, ugDestroyWindow, w);
230
231	w->next = _ug->winlist;
232	_ug->winlist = w;
233	w->prev = 0;
234
235	if (w->next)
236	{
237		w->next->prev = w;
238	}
239
240	w->width = ftk_widget_width(w->win);
241	w->height = ftk_widget_height(w->win);
242	
243	w->surface = eglCreateWindowSurface(_ug->egldpy, w->eglconfig, (NativeWindowType)(w->win), 0);
244	
245	w->eglctx = eglCreateContext(_ug->egldpy, w->eglconfig, NULL, NULL);
246	bind_context(_ug, w);
247	
248	return (UGWindow)w;
249}
250
251void APIENTRY ugDestroyWindow(UGWindow uwin) {
252	UGWindow_t* w = (UGWindow_t*)uwin;
253	UGCtx_t* ug = w->ug;
254	eglDestroySurface(ug->egldpy, w->surface);
255
256	if (ug->winlist == w) ug->winlist = w->next;
257	if (w->next) w->next->prev = w->prev;
258	if (w->prev) w->prev->next = w->next;
259	if(w->painter_idle != NULL) ftk_source_unref(w->painter_idle);
260	free(w);
261}
262
263void APIENTRY
264ugReshapeFunc(UGWindow uwin, void (*f)(UGWindow uwin, int width, int height)) {
265	UGWindow_t *w = (UGWindow_t*)uwin;
266	w->reshape = f;
267	if(f != NULL)
268	{
269		f(uwin, w->width, w->height);
270	}
271
272	return;
273}
274
275void APIENTRY
276ugDisplayFunc(UGWindow uwin, void (*f)(UGWindow uwin)) {
277	UGWindow_t *w = (UGWindow_t*)uwin;
278	w->draw = f;
279
280	ugPostRedisplay(uwin);
281}
282
283void APIENTRY
284ugKeyboardFunc(UGWindow uwin, void (*f)(UGWindow uwin, int key, int x, int y)) {
285	UGWindow_t *w = (UGWindow_t*)uwin;
286	w->kbd = f;
287}
288
289void APIENTRY
290ugPointerFunc(UGWindow uwin, void (*f)(UGWindow uwin, int button, int state, int x, int y)) {
291	UGWindow_t *w = (UGWindow_t*)uwin;
292	w->pointer = f;
293}
294
295void APIENTRY
296ugMotionFunc(UGWindow uwin, void (*f)(UGWindow uwin, int x, int y)) {
297	UGWindow_t *w = (UGWindow_t*)uwin;
298	w->motion = f;
299}
300
301static Ret	on_idle(void* user_data)
302{
303	uGIdle idle = user_data;
304
305	idle((UGWindow)context->win);
306
307	return RET_REMOVE;
308}
309
310void APIENTRY ugIdleFunc(UGCtx ug, void (*f)(UGWindow w)) 
311{
312	FtkSource* source = ftk_source_idle_create(on_idle, f);
313
314	ftk_main_loop_add_source(ftk_default_main_loop(), source);
315
316	return;
317}
318
319void APIENTRY ugMainLoop(UGCtx ug) 
320{
321	context = (UGCtx_t *) ug;
322
323	ftk_run();
324
325	return;
326}
327
328static Ret redisplay(void* ctx)
329{
330	UGWindow_t* win = ctx;
331
332	if(win != NULL && win->draw != NULL)
333	{
334		win->draw((UGWindow)win);
335	}
336
337	return RET_REMOVE;
338}
339
340void APIENTRY ugPostRedisplay(UGWindow uwin) 
341{
342	UGWindow_t* w = (UGWindow_t*)uwin;
343	
344	return_if_fail(w != NULL);
345
346	if(w->painter_idle == NULL)
347	{
348		w->painter_idle = ftk_source_idle_create(redisplay, w);
349	}
350
351	ftk_source_ref(w->painter_idle);
352	ftk_main_loop_add_source(ftk_default_main_loop(), w->painter_idle);
353
354	return;
355}
356
357void APIENTRY ugSwapBuffers(UGWindow uwin) 
358{
359	UGWindow_t* w = (UGWindow_t*)uwin;
360
361	eglSwapBuffers(context->dpy, w->surface);
362}
363