discomfitor pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=c67f50b40aaf2595e21373bf89b53bc1edec44a4
commit c67f50b40aaf2595e21373bf89b53bc1edec44a4 Author: Derek Foreman <der...@osg.samsung.com> Date: Mon Mar 28 12:56:23 2016 -0500 evas-wayland-egl: Add www protocol handling to wayland-egl engine Use the new post-processing API and www extension to implement CSS effects for wayland-egl applications. Signed-off-by: Derek Foreman <der...@osg.samsung.com> Signed-off-by: Mike Blumenkrantz <zm...@osg.samsung.com> --- src/Makefile_Evas.am | 4 +- src/modules/evas/engines/wayland_egl/evas_engine.c | 43 + src/modules/evas/engines/wayland_egl/evas_engine.h | 25 + .../evas/engines/wayland_egl/evas_wl_main.c | 58 +- src/modules/evas/engines/wayland_egl/www.c | 885 +++++++++++++++++++++ src/modules/evas/engines/wayland_egl/www.h | 52 ++ 6 files changed, 1064 insertions(+), 3 deletions(-) diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index 0769220..d2e15de 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -1193,7 +1193,9 @@ dist_installed_evasmainheaders_DATA += modules/evas/engines/wayland_egl/Evas_Eng WAYLAND_EGL_SOURCES = \ modules/evas/engines/wayland_egl/evas_engine.c \ modules/evas/engines/wayland_egl/evas_wl_main.c \ -modules/evas/engines/wayland_egl/evas_engine.h +modules/evas/engines/wayland_egl/evas_engine.h \ +modules/evas/engines/wayland_egl/www.c \ +modules/evas/engines/wayland_egl/www.h if EVAS_STATIC_BUILD_WAYLAND_EGL lib_evas_libevas_la_SOURCES += $(WAYLAND_EGL_SOURCES) lib_evas_libevas_la_CPPFLAGS += @evas_engine_wayland_egl_cflags@ diff --git a/src/modules/evas/engines/wayland_egl/evas_engine.c b/src/modules/evas/engines/wayland_egl/evas_engine.c index 0e27ade..aef2120 100644 --- a/src/modules/evas/engines/wayland_egl/evas_engine.c +++ b/src/modules/evas/engines/wayland_egl/evas_engine.c @@ -62,6 +62,11 @@ Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe = NULL; Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done = NULL; Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize = NULL; Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump = NULL; +Evas_GL_Common_Context_Call glsym_evas_gl_common_context_unredirect = NULL; +Evas_GL_Common_Context_Call glsym_evas_gl_common_context_redirect = NULL; +Evas_GL_Common_Context_Call glsym_evas_gl_common_context_redirect_bind = NULL; +Evas_GL_Common_Context_Call glsym_evas_gl_common_context_redirect_unbind = NULL; +Evas_GL_Common_Context_Call_GLuint_Return glsym_evas_gl_common_context_redirect_texture_get = NULL; Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock = NULL; Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock = NULL; Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_relax = NULL; @@ -73,6 +78,17 @@ void (*glsym_glEGLImageTargetTexture2DOES) (int a, void *b) = NULL; unsigned int (*glsym_eglSwapBuffersWithDamage) (EGLDisplay a, void *b, const EGLint *d, EGLint c) = NULL; unsigned int (*glsym_eglSetDamageRegionKHR) (EGLDisplay a, EGLSurface b, EGLint *c, EGLint d) = NULL; unsigned int (*glsym_eglQueryWaylandBufferWL)(EGLDisplay a, struct wl_resource *b, EGLint c, EGLint *d) = NULL; +GLuint (*glsym_glCreateShader) (GLenum a) = NULL; +void (*glsym_glShaderSource) (GLuint a, GLsizei b, const GLchar **c, const GLint *d) = NULL; +void (*glsym_glCompileShader) (GLuint a) = NULL; +void (*glsym_glGetShaderiv) (GLuint a, GLenum b, GLint *c) = NULL; +void (*glsym_glGetShaderInfoLog) (GLuint a, GLsizei b, GLsizei *c, GLchar *d) = NULL; +GLuint (*glsym_glCreateProgram) (void) = NULL; +void (*glsym_glAttachShader) (GLuint a, GLuint b) = NULL; +void (*glsym_glBindAttribLocation) (GLuint a, GLuint b, const GLchar *c) = NULL; +void (*glsym_glLinkProgram) (GLuint a) = NULL; +void (*glsym_glGetProgramiv) (GLuint a, GLenum b, GLint *c) = NULL; +void (*glsym_glGetProgramInfoLog) (GLuint a, GLsizei b, GLsizei *c, GLchar *d) = NULL; /* local variables */ static Eina_Bool initted = EINA_FALSE; @@ -124,6 +140,11 @@ gl_symbols(void) LINK2GENERIC(evas_gl_common_context_newframe); LINK2GENERIC(evas_gl_common_context_done); LINK2GENERIC(evas_gl_common_context_resize); + LINK2GENERIC(evas_gl_common_context_unredirect); + LINK2GENERIC(evas_gl_common_context_redirect); + LINK2GENERIC(evas_gl_common_context_redirect_bind); + LINK2GENERIC(evas_gl_common_context_redirect_unbind); + LINK2GENERIC(evas_gl_common_context_redirect_texture_get); LINK2GENERIC(evas_gl_common_buffer_dump); LINK2GENERIC(evas_gl_preload_render_lock); LINK2GENERIC(evas_gl_preload_render_unlock); @@ -174,6 +195,28 @@ gl_symbols(void) FINDSYM(glsym_eglQueryWaylandBufferWL, "eglQueryWaylandBufferWL", glsym_func_uint); + FINDSYM(glsym_glCreateShader, "glCreateShader", glsym_func_uint); + + FINDSYM(glsym_glShaderSource, "glShaderSource", glsym_func_void); + + FINDSYM(glsym_glCompileShader, "glCompileShader", glsym_func_void); + + FINDSYM(glsym_glGetShaderiv, "glGetShaderiv", glsym_func_void); + + FINDSYM(glsym_glGetShaderInfoLog, "glGetShaderInfoLog", glsym_func_void); + + FINDSYM(glsym_glCreateProgram, "glCreateProgram", glsym_func_uint); + + FINDSYM(glsym_glAttachShader, "glAttachShader", glsym_func_void); + + FINDSYM(glsym_glBindAttribLocation, "glBindAttribLocation", glsym_func_void); + + FINDSYM(glsym_glLinkProgram, "glLinkProgram", glsym_func_void); + + FINDSYM(glsym_glGetProgramiv, "glGetProgramiv", glsym_func_void); + + FINDSYM(glsym_glGetProgramInfoLog, "glGetProgramInfoLog", glsym_func_void); + done = EINA_TRUE; } diff --git a/src/modules/evas/engines/wayland_egl/evas_engine.h b/src/modules/evas/engines/wayland_egl/evas_engine.h index a4ccbf8..a7bc7c7 100644 --- a/src/modules/evas/engines/wayland_egl/evas_engine.h +++ b/src/modules/evas/engines/wayland_egl/evas_engine.h @@ -7,6 +7,8 @@ # include "Evas.h" # include "Evas_Engine_Wayland_Egl.h" +# include "www.h" + /* NB: This already includes wayland-client.h */ # include <wayland-egl.h> @@ -81,6 +83,11 @@ struct _Outbuf Eina_Bool lost_back : 1; Eina_Bool surf : 1; + + Model *model; + Eina_Bool redirected : 1; + + float offset_x, offset_y; }; struct _Context_3D @@ -100,6 +107,11 @@ extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use; extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe; extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done; extern Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize; +extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_unredirect; +extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_redirect; +extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_redirect_bind; +extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_redirect_unbind; +extern Evas_GL_Common_Context_Call_GLuint_Return glsym_evas_gl_common_context_redirect_texture_get; extern Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump; extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock; extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock; @@ -107,6 +119,19 @@ extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock; extern unsigned int (*glsym_eglSwapBuffersWithDamage) (EGLDisplay a, void *b, const EGLint *d, EGLint c); extern unsigned int (*glsym_eglSetDamageRegionKHR) (EGLDisplay a, EGLSurface b, EGLint *c, EGLint d); +extern GLuint (*glsym_glCreateShader) (GLenum a); +extern void (*glsym_glShaderSource) (GLuint a, GLsizei b, const GLchar **c, const GLint *d); +extern void (*glsym_glCompileShader) (GLuint a); +extern void (*glsym_glGetShaderiv) (GLuint a, GLenum b, GLint *c); +extern void (*glsym_glGetShaderInfoLog) (GLuint a, GLsizei b, GLsizei *c, GLchar *d); +extern GLuint (*glsym_glCreateProgram) (void); +extern void (*glsym_glAttachShader) (GLuint a, GLuint b); +extern void (*glsym_glBindAttribLocation) (GLuint a, GLuint b, const GLchar *c); +extern void (*glsym_glLinkProgram) (GLuint a); +extern void (*glsym_glGetProgramiv) (GLuint a, GLenum b, GLint *c); +extern void (*glsym_glGetProgramInfoLog) (GLuint a, GLsizei b, GLsizei *c, GLchar *d); + + Outbuf *eng_window_new(Evas *evas, Evas_Engine_Info_Wayland_Egl *einfo, int w, int h, Render_Engine_Swap_Mode swap_mode); void eng_window_free(Outbuf *gw); void eng_window_use(Outbuf *gw); diff --git a/src/modules/evas/engines/wayland_egl/evas_wl_main.c b/src/modules/evas/engines/wayland_egl/evas_wl_main.c index e65570c..59806cf 100644 --- a/src/modules/evas/engines/wayland_egl/evas_wl_main.c +++ b/src/modules/evas/engines/wayland_egl/evas_wl_main.c @@ -217,7 +217,8 @@ eng_window_free(Outbuf *gw) eglReleaseThread(); context = EGL_NO_CONTEXT; } - + free(gw->model); + gw->model = NULL; free(gw); } @@ -314,6 +315,11 @@ eng_window_resurf(Outbuf *gw) void eng_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth EINA_UNUSED) { + if (!ob->model) ob->model = wobbly_create(0, 0, w, h); + wobbly_resize(ob->model, w, h); + glsym_evas_gl_common_context_unredirect(ob->gl_context); + ob->redirected = EINA_FALSE; + ob->w = w; ob->h = h; ob->rot = rot; @@ -361,6 +367,11 @@ eng_outbuf_rotation_get(Outbuf *ob) Render_Engine_Swap_Mode eng_outbuf_swap_mode_get(Outbuf *ob) { + if (ob->redirected) + { + ob->prev_age = 0; + return MODE_FULL; + } if ((ob->swap_mode == MODE_AUTO) && (extn_have_buffer_age)) { Render_Engine_Swap_Mode swap_mode; @@ -488,6 +499,8 @@ eng_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update EINA_UNUSED, int x void eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode) { + Eina_Bool effect_continues = EINA_FALSE; + if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end; if (!_re_wincheck(ob)) goto end; @@ -507,7 +520,33 @@ eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode) if (ob->info->callback.pre_swap) ob->info->callback.pre_swap(ob->info->callback.data, ob->evas); - if ((glsym_eglSwapBuffersWithDamage) && (rects) && + if (ob->model) effect_continues = wobbly_process(ob->model, ob->info, + ob->w, ob->h, + ob->redirected); + + if (ob->redirected) + { + float tlx, tly, brx, bry; + int w, h; + + wobbly_bounds(ob->model, &tlx, &tly, &brx, &bry); + w = brx - tlx; + h = bry - tly; + + wl_egl_window_resize(ob->win, w, h, + tlx - ob->offset_x, + tly - ob->offset_y); + ob->offset_x = tlx; + ob->offset_y = tly; + glsym_evas_gl_common_context_redirect_unbind(ob->gl_context); + glViewport(0, 0, w, h); + wobbly_draw(ob->gl_context, ob->model); + wl_surface_set_opaque_region(ob->info->info.surface, NULL); + eglSwapBuffers(ob->egl_disp, ob->egl_surface[0]); + glsym_evas_gl_common_context_redirect_bind(ob->gl_context); + glViewport(0, 0, ob->w, ob->h); + } + else if ((glsym_eglSwapBuffersWithDamage) && (rects) && (ob->swap_mode != MODE_FULL)) { EGLint num = 0, *result = NULL, i = 0; @@ -530,6 +569,21 @@ eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode) else eglSwapBuffers(ob->egl_disp, ob->egl_surface[0]); + if (ob->redirected && !effect_continues) ob->info->wobbling = EINA_TRUE; + else ob->info->wobbling = effect_continues; + + if (effect_continues) + { + glsym_evas_gl_common_context_redirect(ob->gl_context); + ob->redirected = EINA_TRUE; + } + else + { + ob->offset_x = 0; + ob->offset_y = 0; + glsym_evas_gl_common_context_unredirect(ob->gl_context); + ob->redirected = EINA_FALSE; + } if (ob->info->callback.post_swap) ob->info->callback.post_swap(ob->info->callback.data, ob->evas); diff --git a/src/modules/evas/engines/wayland_egl/www.c b/src/modules/evas/engines/wayland_egl/www.c new file mode 100644 index 0000000..c6bb5ca --- /dev/null +++ b/src/modules/evas/engines/wayland_egl/www.c @@ -0,0 +1,885 @@ +/* + * Copyright © 2005 Novell, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Novell, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * Novell, Inc. makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <dav...@novell.com> + */ + +/* + * Spring model implemented by Kristian Hogsberg. + */ + +#include "evas_engine.h" +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <Eina.h> +#include <Evas.h> +#include <EGL/egl.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#include "www.h" + +# define GRID_WIDTH 4 +# define GRID_HEIGHT 4 + +# define MODEL_MAX_SPRINGS (GRID_WIDTH * GRID_HEIGHT * 2) + +# define MASS 15.0f + +# define MAXSHORT 32767 +# define MINSHORT -MAXSHORT + +# define WOBBLY_GRID_RESOLUTION 32 +# define WOBBLY_MIN_GRID_SIZE 64 + +typedef struct _xy_pair +{ + float x, y; +} Point, Vector; + +typedef struct _Object +{ + Vector force; + Point position; + Vector velocity; + float theta; + Eina_Bool immobile; +} Object; + +typedef struct _Spring +{ + Object *a; + Object *b; + Vector offset; +} Spring; + +typedef struct _Model +{ + Object *objects; + int numObjects; + Spring springs[MODEL_MAX_SPRINGS]; + int numSprings; + Object *anchorObject; + float steps; + Point topLeft; + Point bottomRight; + + int indexSize; + GLushort *indices; + int vertexStride; + GLfloat *vertices; + int vertexSize; + int texCoordSize; + + int wobbleGrace; + int vCount; + int indexCount; + struct timeval tv; + + GLuint fs; + GLuint vs; + GLuint prog; +} Model; + +static const GLchar *prog_vs = + "attribute vec3 pos;\n" + "attribute vec2 tc;\n" + "varying vec2 f_tc;\n" + "void main()\n" + "{\n" + " gl_Position = vec4(pos, 1.0);\n" + " f_tc = tc;\n" + "}\n"; + +static const GLchar *prog_fs = + "precision mediump float;\n" + "varying vec2 f_tc;\n" + "uniform sampler2D ts;\n" + "void main()\n" + "{\n" + " gl_FragColor = texture2D(ts, f_tc);\n" + "}\n"; + +static Eina_Bool +setup_shaders(Model *m) +{ + GLint err; + char errbuf[2048]; + + m->vs = glsym_glCreateShader(GL_VERTEX_SHADER); + glsym_glShaderSource(m->vs, 1, &prog_vs, NULL); + glsym_glCompileShader(m->vs); + glsym_glGetShaderiv(m->vs, GL_COMPILE_STATUS, &err); + if (!err) + { + glsym_glGetShaderInfoLog(m->vs, sizeof errbuf, NULL, errbuf); + fprintf(stderr, "vs sigh: %s\n", errbuf); + return EINA_FALSE; + } + + m->fs = glsym_glCreateShader(GL_FRAGMENT_SHADER); + glsym_glShaderSource(m->fs, 1, &prog_fs, NULL); + glsym_glCompileShader(m->fs); + glsym_glGetShaderiv(m->fs, GL_COMPILE_STATUS, &err); + if (!err) + { + glsym_glGetShaderInfoLog(m->fs, sizeof errbuf, NULL, errbuf); + fprintf(stderr, "fs sigh: %s\n", errbuf); + return EINA_FALSE; + } + + m->prog = glsym_glCreateProgram(); + glsym_glAttachShader(m->prog, m->vs); + glsym_glAttachShader(m->prog, m->fs); + glsym_glBindAttribLocation(m->prog, 0, "tc"); + glsym_glBindAttribLocation(m->prog, 1, "pos"); + glsym_glLinkProgram(m->prog); + glsym_glGetProgramiv(m->prog, GL_LINK_STATUS, &err); + if (!err) + { + glsym_glGetProgramInfoLog(m->prog, sizeof errbuf, NULL, errbuf); + fprintf(stderr, "link : %s\n", errbuf); + return EINA_FALSE; + } + return EINA_TRUE; +} + + +static void +objectInit(Object *object, + float positionX, + float positionY, + float velocityX, + float velocityY) +{ + object->force.x = 0; + object->force.y = 0; + + object->position.x = positionX; + object->position.y = positionY; + + object->velocity.x = velocityX; + object->velocity.y = velocityY; + + object->theta = 0; + object->immobile = EINA_FALSE; +} + +static void +springInit(Spring *spring, + Object *a, + Object *b, + float offsetX, + float offsetY) +{ + spring->a = a; + spring->b = b; + spring->offset.x = offsetX; + spring->offset.y = offsetY; +} + +static void +modelCalcBounds(Model *model) +{ + int i; + + model->topLeft.x = MAXSHORT; + model->topLeft.y = MAXSHORT; + model->bottomRight.x = MINSHORT; + model->bottomRight.y = MINSHORT; + + for (i = 0; i < model->numObjects; i++) + { + if (model->objects[i].position.x < model->topLeft.x) + model->topLeft.x = model->objects[i].position.x; + else if (model->objects[i].position.x > model->bottomRight.x) + model->bottomRight.x = model->objects[i].position.x; + + if (model->objects[i].position.y < model->topLeft.y) + model->topLeft.y = model->objects[i].position.y; + else if (model->objects[i].position.y > model->bottomRight.y) + model->bottomRight.y = model->objects[i].position.y; + } +} + +static void +modelAddSpring(Model *model, + Object *a, + Object *b, + float offsetX, + float offsetY) +{ + Spring *spring; + + spring = &model->springs[model->numSprings]; + model->numSprings++; + + springInit(spring, a, b, offsetX, offsetY); +} + +static void +modelSetMiddleAnchor(Model *model, + int x, + int y, + int width, + int height) +{ + float gx, gy; + + gx = ((GRID_WIDTH - 1) / 2 * width) / (float)(GRID_WIDTH - 1); + gy = ((GRID_HEIGHT - 1) / 2 * height) / (float)(GRID_HEIGHT - 1); + + if (model->anchorObject) + model->anchorObject->immobile = EINA_FALSE; + + model->anchorObject = &model->objects[GRID_WIDTH * + ((GRID_HEIGHT - 1) / 2) + + (GRID_WIDTH - 1) / 2]; + model->anchorObject->position.x = x + gx; + model->anchorObject->position.y = y + gy; + + model->anchorObject->immobile = EINA_TRUE; +} + +static void +modelAdjustObjectPosition(Model *model, + Object *object, + int x, + int y, + int width, + int height) +{ + Object *o; + int gridX, gridY, i = 0; + + for (gridY = 0; gridY < GRID_HEIGHT; gridY++) + { + for (gridX = 0; gridX < GRID_WIDTH; gridX++) + { + o = &model->objects[i]; + if (o == object) + { + o->position.x = x + (gridX * width) / (GRID_WIDTH - 1); + o->position.y = y + (gridY * height) / (GRID_HEIGHT - 1); + + return; + } + + i++; + } + } +} + +static void +modelInitObjects(Model *model, + int x, + int y, + int width, + int height) +{ + int gridX, gridY, i = 0; + float gw, gh; + + gw = GRID_WIDTH - 1; + gh = GRID_HEIGHT - 1; + + for (gridY = 0; gridY < GRID_HEIGHT; gridY++) + { + for (gridX = 0; gridX < GRID_WIDTH; gridX++) + { + objectInit(&model->objects[i], + x + (gridX * width) / gw, + y + (gridY * height) / gh, + 0, 0); + i++; + } + } + + modelSetMiddleAnchor(model, x, y, width, height); +} + +static void +modelAdjustObjectsForShiver(Model *model, + int x, + int y, + int width, + int height) +{ + int gridX, gridY, i = 0; + float vX, vY; + float w, h; + float scale; + + w = width; + h = height; + + for (gridY = 0; gridY < GRID_HEIGHT; gridY++) + { + for (gridX = 0; gridX < GRID_WIDTH; gridX++) + { + if (!model->objects[i].immobile) + { + vX = model->objects[i].position.x - (x + w / 2); + vY = model->objects[i].position.y - (y + h / 2); + + vX /= w; + vY /= h; + + scale = ((float)rand() * 7.5f) / RAND_MAX; + + model->objects[i].velocity.x += vX * scale; + model->objects[i].velocity.y += vY * scale; + } + + i++; + } + } +} + +static void +modelInitSprings(Model *model, + int x EINA_UNUSED, + int y EINA_UNUSED, + int width, + int height) +{ + int gridX, gridY, i = 0; + float hpad, vpad; + + model->numSprings = 0; + + hpad = ((float)width) / (GRID_WIDTH - 1); + vpad = ((float)height) / (GRID_HEIGHT - 1); + + for (gridY = 0; gridY < GRID_HEIGHT; gridY++) + { + for (gridX = 0; gridX < GRID_WIDTH; gridX++) + { + if (gridX > 0) + modelAddSpring(model, + &model->objects[i - 1], + &model->objects[i], + hpad, 0); + + if (gridY > 0) + modelAddSpring(model, + &model->objects[i - GRID_WIDTH], + &model->objects[i], + 0, vpad); + + i++; + } + } +} + +Model * +wobbly_create(int x, + int y, + int width, + int height) +{ + Model *model; + + model = calloc(sizeof (Model), 1); + if (!model) + return 0; + + model->numObjects = GRID_WIDTH * GRID_HEIGHT; + model->objects = malloc(sizeof (Object) * model->numObjects); + if (!model->objects) + { + free(model); + return 0; + } + + model->anchorObject = 0; + model->numSprings = 0; + + model->steps = 0; + + modelInitObjects(model, x, y, width, height); + modelInitSprings(model, x, y, width, height); + + modelCalcBounds(model); + + setup_shaders(model); + + return model; +} + +static void +objectApplyForce(Object *object, + float fx, + float fy) +{ + object->force.x += fx; + object->force.y += fy; +} + +static void +springExertForces(Spring *spring, + float k) +{ + Vector da, db; + Vector a, b; + + a = spring->a->position; + b = spring->b->position; + + da.x = 0.5f * (b.x - a.x - spring->offset.x); + da.y = 0.5f * (b.y - a.y - spring->offset.y); + + db.x = 0.5f * (a.x - b.x + spring->offset.x); + db.y = 0.5f * (a.y - b.y + spring->offset.y); + + objectApplyForce(spring->a, k * da.x, k * da.y); + objectApplyForce(spring->b, k * db.x, k * db.y); +} + +static float +modelStepObject(Object *object, float *force) +{ + float friction = 0.8f; + + object->theta += 0.05f; + + if (object->immobile) + { + object->velocity.x = 0.0f; + object->velocity.y = 0.0f; + + object->force.x = 0.0f; + object->force.y = 0.0f; + + *force = 0.0f; + + return 0.0f; + } + else + { + object->force.x -= friction * object->velocity.x; + object->force.y -= friction * object->velocity.y; + + object->velocity.x += object->force.x / MASS; + object->velocity.y += object->force.y / MASS; + + object->position.x += object->velocity.x; + object->position.y += object->velocity.y; + + *force = fabs(object->force.x) + fabs(object->force.y); + + object->force.x = 0.0f; + object->force.y = 0.0f; + + return fabs(object->velocity.x) + fabs(object->velocity.y); + } +} + +int +modelStep(Model *model, float time) +{ + float k = 0.9; + int i, j, steps; + float velocitySum = 0.0f; + float force, forceSum = 0.0f; + int wobbly = 0; + + if (model->wobbleGrace) + { + model->wobbleGrace--; + wobbly |= 4; + } + + model->steps += time / 15.0f; + steps = floor(model->steps); + model->steps -= steps; + + if (!steps) + return 1; + + for (j = 0; j < steps; j++) + { + for (i = 0; i < model->numSprings; i++) + springExertForces(&model->springs[i], k); + + for (i = 0; i < model->numObjects; i++) + { + velocitySum += modelStepObject(&model->objects[i], &force); + forceSum += force; + } + } + + modelCalcBounds(model); + + if (velocitySum > 0.5f) + wobbly |= 1; //WobblyVelocity; + + if (forceSum > 20.0f) + wobbly |= 2; //WobblyForce; + + return wobbly; +} + +static void +bezierPatchEvaluate(Model *model, + float u, + float v, + float *patchX, + float *patchY) +{ + float coeffsU[4], coeffsV[4]; + float x, y; + int i, j; + + coeffsU[0] = (1 - u) * (1 - u) * (1 - u); + coeffsU[1] = 3 * u * (1 - u) * (1 - u); + coeffsU[2] = 3 * u * u * (1 - u); + coeffsU[3] = u * u * u; + + coeffsV[0] = (1 - v) * (1 - v) * (1 - v); + coeffsV[1] = 3 * v * (1 - v) * (1 - v); + coeffsV[2] = 3 * v * v * (1 - v); + coeffsV[3] = v * v * v; + + x = y = 0.0f; + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + x += coeffsU[i] * coeffsV[j] * + model->objects[j * GRID_WIDTH + i].position.x; + y += coeffsU[i] * coeffsV[j] * + model->objects[j * GRID_WIDTH + i].position.y; + } + } + + *patchX = x; + *patchY = y; +} + +static float +objectDistance(Object *object, + float x, + float y) +{ + float dx, dy; + + dx = object->position.x - x; + dy = object->position.y - y; + + return sqrt(dx * dx + dy * dy); +} + +static Object * +modelFindNearestObject(Model *model, + float x, + float y) +{ + Object *object = &model->objects[0]; + float distance, minDistance = 0.0; + int i; + + for (i = 0; i < model->numObjects; i++) + { + distance = objectDistance(&model->objects[i], x, y); + if (i == 0 || distance < minDistance) + { + minDistance = distance; + object = &model->objects[i]; + } + } + + return object; +} + +static Eina_Bool +moreWindowVertices(Model *m, int newSize) +{ + if (newSize > m->vertexSize) + { + GLfloat *vertices; + + vertices = realloc(m->vertices, sizeof(GLfloat) * newSize); + if (!vertices) return EINA_FALSE; + + m->vertices = vertices; + m->vertexSize = newSize; + } + + return EINA_TRUE; +} + +static Eina_Bool +moreWindowIndices(Model *m, int newSize) +{ + if (newSize > m->indexSize) + { + GLushort *indices; + + indices = realloc(m->indices, sizeof(GLushort) * newSize); + if (!indices) return EINA_FALSE; + + m->indices = indices; + m->indexSize = newSize; + } + + return EINA_TRUE; +} + +void +wobblyGeometryDo(Model *m, int in_w, int in_h) +{ + int nVertices, nIndices; + GLushort *i; + GLfloat *v; + int x1, y1, x2, y2; + float width, height; + float deformedX, deformedY; + int x, y, iw, ih, wx, wy; + int vSize; + int gridW, gridH; + int bound_w = m->bottomRight.x - m->topLeft.x; + int bound_h = m->bottomRight.y - m->topLeft.y; + + wx = 0; + wy = 0; + width = in_w; + height = in_h; + + gridW = width / WOBBLY_GRID_RESOLUTION; + if (gridW < WOBBLY_MIN_GRID_SIZE) + gridW = WOBBLY_MIN_GRID_SIZE; + + gridH = height / WOBBLY_GRID_RESOLUTION; + if (gridH < WOBBLY_MIN_GRID_SIZE) + gridH = WOBBLY_MIN_GRID_SIZE; + + vSize = 3 + 2; /* 3 vert, 2 texcoord */ + + nVertices = m->vCount = 0; + nIndices = m->indexCount = 0; + + v = m->vertices + (nVertices * vSize); + i = m->indices + nIndices; + + x1 = 0; + y1 = 0; + x2 = width; + y2 = height; + + iw = ((x2 - x1 - 1) / gridW) + 1; + ih = ((y2 - y1 - 1) / gridH) + 1; + + if (nIndices + (iw * ih * 6) > m->indexSize) + { + if (!moreWindowIndices(m, nIndices + (iw * ih * 6))) + return; + + i = m->indices + nIndices; + } + + iw++; + ih++; + + for (y = 0; y < ih - 1; y++) + { + for (x = 0; x < iw - 1; x++) + { + *i++ = nVertices + iw * (y + 1) + x; + *i++ = nVertices + iw * (y + 1) + x + 1; + *i++ = nVertices + iw * y + x + 1; + + *i++ = nVertices + iw * y + x + 1; + *i++ = nVertices + iw * y + x; + *i++ = nVertices + iw * (y + 1) + x; + + nIndices += 6; + } + } + + if (((nVertices + iw * ih) * vSize) > m->vertexSize) + { + if (!moreWindowVertices(m, (nVertices + iw * ih) * vSize)) + return; + + v = m->vertices + (nVertices * vSize); + } + + for (y = y1;; y += gridH) + { + if (y > y2) + y = y2; + + for (x = x1;; x += gridW) + { + if (x > x2) + x = x2; + + bezierPatchEvaluate(m, + (x - wx) / width, + (y - wy) / height, + &deformedX, + &deformedY); + + //Tex co-ord + *v++ = x / width; + *v++ = y / height; + + // vertex + *v++ = -1 + ((deformedX - m->topLeft.x) / (bound_w / 2.0)); + *v++ = -1 + ((deformedY - m->topLeft.y) / (bound_h / 2.0)); + *v++ = 0.0; + + nVertices++; + + if (x == x2) + break; + } + + if (y == y2) + break; + } + + m->vCount = nVertices; + m->vertexStride = vSize; + m->texCoordSize = 2; + m->indexCount = nIndices; +} + +void +wobblyMap(Model *m, int w, int h) +{ + modelInitObjects(m, 0, 0, w, h); + modelInitSprings(m, 0, 0, w, h); + modelSetMiddleAnchor(m, 0, 0, w, h); + modelAdjustObjectsForShiver(m, 0, 0, w, h); + m->wobbleGrace = 10; +} + +void +wobblyMove(Model *m, int dx, int dy, int w, int h) +{ + m->wobbleGrace = 10; + modelAdjustObjectPosition(m, m->anchorObject, 0, 0, w, h); + m->anchorObject->position.x += dx; + m->anchorObject->position.y += dy; +} + +void +wobblyAnchorRelease(Model *m) +{ + if (m->anchorObject) + m->anchorObject->immobile = EINA_FALSE; +} + +void +wobblyAnchor(Model *m, int cx, int cy, int w, int h) +{ + wobblyAnchorRelease(m); + m->anchorObject = modelFindNearestObject(m, cx, h - cy); + m->anchorObject->immobile = EINA_TRUE; + modelAdjustObjectPosition(m, m->anchorObject, 0, 0, w, h); + m->wobbleGrace = 10; +} + +void +wobbly_resize(Model *m, int dwidth, int dheight) +{ + m->wobbleGrace = 10; + modelInitObjects(m, 0, 0, dwidth, dheight); + modelInitSprings(m, 0, 0, dwidth, dheight); + modelCalcBounds(m); +} + +void +wobbly_draw(Evas_Engine_GL_Context *gl_context, Model *m) +{ + GLuint tex; + + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(m->prog); + tex = glsym_evas_gl_common_context_redirect_texture_get(gl_context); + glBindTexture(GL_TEXTURE_2D, tex); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), m->vertices); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), m->vertices + 2); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glDrawElements(GL_TRIANGLES, m->indexCount, GL_UNSIGNED_SHORT, m->indices); + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(0); +} + +Eina_Bool +wobbly_process(Model *m, Evas_Engine_Info_Wayland_Egl *info, int w, int h, Eina_Bool redirected) +{ + int ret = EINA_FALSE; + + if (info->just_mapped) + { + info->just_mapped = EINA_FALSE; + wobblyMap(m, w, h); + return EINA_TRUE; + } + + if (info->drag_start) + { + wobblyAnchor(m, info->x_cursor, info->y_cursor, w, h); + ret = EINA_TRUE; + } + if (!info->resizing && (info->x_rel || info->y_rel)) + { + wobblyMove(m, info->x_rel, -info->y_rel, w, h); + ret = EINA_TRUE; + } + + if (info->drag_stop) + { + wobblyAnchorRelease(m); + ret = EINA_TRUE; + } + + if (redirected) + { + double oldms, ms; + + oldms = m->tv.tv_usec / 1000 + m->tv.tv_sec * 1000; + gettimeofday(&m->tv, NULL); + ms = m->tv.tv_usec / 1000 + m->tv.tv_sec * 1000 - oldms; + + if (ms > 100) ms = 0; + if (modelStep(m, ms)) ret = EINA_TRUE; + + wobblyGeometryDo(m, w, h); + } + return ret; +} + +void +wobbly_bounds(Model *m, float *tlx, float *tly, float *brx, float *bry) +{ + *tlx = m->topLeft.x; + *tly = m->topLeft.y; + *brx = m->bottomRight.x; + *bry = m->bottomRight.y; +} diff --git a/src/modules/evas/engines/wayland_egl/www.h b/src/modules/evas/engines/wayland_egl/www.h new file mode 100644 index 0000000..99fd09f --- /dev/null +++ b/src/modules/evas/engines/wayland_egl/www.h @@ -0,0 +1,52 @@ +/* + * Copyright C 2005 Novell, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Novell, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * Novell, Inc. makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <dav...@novell.com> + */ + +/* + * Spring model implemented by Kristian Hogsberg. + */ + +#ifndef EVAS_WWW_H +# define EVAS_WWW_H + +# include "../gl_generic/Evas_Engine_GL_Generic.h" + +typedef struct _Model Model; + +Model * +wobbly_create(int x, int y, int width, int height); + +void +wobbly_resize(Model *m, int dw, int dh); + +void +wobbly_draw(Evas_Engine_GL_Context *gl_context, Model *m); + +Eina_Bool +wobbly_process(Model *m, Evas_Engine_Info_Wayland_Egl *info, int w, int h, Eina_Bool redirected); + +void +wobbly_bounds(Model *m, float *tlx, float *tly, float *brx, float *bry); + +#endif --