diff --git a/legacy/evas/src/lib/canvas/evas_map.c b/legacy/evas/src/lib/canvas/evas_map.c index 8e34a0015b..ab8a4b1327 100644 --- a/legacy/evas/src/lib/canvas/evas_map.c +++ b/legacy/evas/src/lib/canvas/evas_map.c @@ -73,6 +73,7 @@ _evas_map_new(int count) Evas_Map *m = calloc(1, sizeof(Evas_Map) + count * sizeof(Evas_Map_Point)); if (!m) return NULL; m->count = count; + m->persp.foc = 0; m->alpha = 1; m->smooth = 1; for (i = 0; i < count; i++) @@ -96,6 +97,7 @@ _evas_map_copy(Evas_Map *dst, const Evas_Map *src) memcpy(dst->points, src->points, src->count * sizeof(Evas_Map_Point)); dst->smooth = src->smooth; dst->alpha = src->alpha; + dst->persp = src->persp; return EINA_TRUE; } @@ -107,6 +109,7 @@ _evas_map_dup(const Evas_Map *orig) memcpy(copy->points, orig->points, orig->count * sizeof(Evas_Map_Point)); copy->smooth = orig->smooth; copy->alpha = orig->alpha; + copy->persp = orig->persp; return copy; } @@ -648,8 +651,8 @@ evas_map_point_coord_set(Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_ if (!m) return; if (idx >= m->count) return; p = m->points + idx; - p->x = x; - p->y = y; + p->x = p->px = x; + p->y = p->py = y; p->z = z; } @@ -832,6 +835,15 @@ _evas_map_util_points_populate(Evas_Map *m, const Evas_Coord x, const Evas_Coord p[3].z = z; p[3].u = 0.0; p[3].v = h; + + p[0].px = p[0].x; + p[0].py = p[0].y; + p[1].px = p[1].x; + p[1].py = p[1].y; + p[2].px = p[2].x; + p[2].py = p[2].y; + p[3].px = p[3].x; + p[3].py = p[3].y; } /** @@ -1023,6 +1035,8 @@ evas_map_util_rotate(Evas_Map *m, double degrees, Evas_Coord cx, Evas_Coord cy) p->x = x + cx; p->y = y + cy; + p->px = p->x; + p->py = p->y; } } @@ -1065,6 +1079,8 @@ evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_ p->x = x + cx; p->y = y + cy; + p->px = p->x; + p->py = p->y; } } @@ -1134,6 +1150,8 @@ evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz, p->x = x + cx; p->y = y + cy; p->z = z + cz; + p->px = p->x; + p->py = p->y; } } @@ -1237,7 +1255,7 @@ evas_map_util_3d_lighting(Evas_Map *m, /** * Apply a perspective transform to the map - * +* * This applies a given perspective (3D) to the map coordinates. X, Y and Z * values are used. The px and py points specify the "infinite distance" point * in the 3D conversion (where all lines converge to like when artists draw @@ -1268,6 +1286,10 @@ evas_map_util_3d_perspective(Evas_Map *m, p = m->points; p_end = p + m->count; + m->persp.px = px; + m->persp.py = py; + m->persp.z0 = z0; + m->persp.foc = foc; for (; p < p_end; p++) { Evas_Coord x, y, zz; diff --git a/legacy/evas/src/lib/canvas/evas_object_image.c b/legacy/evas/src/lib/canvas/evas_object_image.c index 32867d424c..ed377d3100 100644 --- a/legacy/evas/src/lib/canvas/evas_object_image.c +++ b/legacy/evas/src/lib/canvas/evas_object_image.c @@ -2442,13 +2442,19 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su p = obj->cur.map->points; p_end = p + 4; pt = pts; - + + pts[0].px = obj->cur.map->persp.px << FP; + pts[0].py = obj->cur.map->persp.py << FP; + pts[0].foc = obj->cur.map->persp.foc << FP; + pts[0].z0 = obj->cur.map->persp.z0 << FP; // draw geom +x +y for (; p < p_end; p++, pt++) { pt->x = (p->x + x) << FP; pt->y = (p->y + y) << FP; pt->z = (p->z) << FP; + pt->x3 = p->px << FP; + pt->y3 = p->py << FP; pt->u = p->u * FP1; pt->v = p->v * FP1; pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b); diff --git a/legacy/evas/src/lib/canvas/evas_render.c b/legacy/evas/src/lib/canvas/evas_render.c index c2a6409f1c..a12e617dca 100644 --- a/legacy/evas/src/lib/canvas/evas_render.c +++ b/legacy/evas/src/lib/canvas/evas_render.c @@ -655,6 +655,11 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface, return clean_them; } + pts[0].px = obj->cur.map->persp.px << FP; + pts[0].py = obj->cur.map->persp.py << FP; + pts[0].foc = obj->cur.map->persp.foc << FP; + pts[0].z0 = obj->cur.map->persp.z0 << FP; + p = obj->cur.map->points; p_end = p + 4; pt = pts; @@ -663,6 +668,8 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface, pt->x = (p->x + off_x) << FP; pt->y = (p->y + off_y) << FP; pt->z = (p->z) << FP; + pt->x3 = p->px << FP; + pt->y3 = p->py << FP; pt->u = p->u * FP1; pt->v = p->v * FP1; pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b); diff --git a/legacy/evas/src/lib/include/evas_common.h b/legacy/evas/src/lib/include/evas_common.h index a7c6c4ff87..49e9f61373 100644 --- a/legacy/evas/src/lib/include/evas_common.h +++ b/legacy/evas/src/lib/include/evas_common.h @@ -766,9 +766,12 @@ struct _RGBA_Polygon_Point struct _RGBA_Map_Point { FPc x, y; // x, y screenspace + FPc x3, y3; // x, y 3d space FPc z; // z in world space. optional FPc u, v; // u, v in tex coords DATA32 col; // color at this point + // for perspective correctness - only point 0 has relevant info + FPc px, py, z0, foc; }; // for fonts... diff --git a/legacy/evas/src/lib/include/evas_private.h b/legacy/evas/src/lib/include/evas_private.h index 39e85e360f..fe1bdcf2ff 100644 --- a/legacy/evas/src/lib/include/evas_private.h +++ b/legacy/evas/src/lib/include/evas_private.h @@ -362,21 +362,24 @@ struct _Evas_Size_Hints struct _Evas_Map_Point { - Evas_Coord x, y, z; + Evas_Coord x, y, z, px, py; double u, v; unsigned char r, g, b, a; }; struct _Evas_Map { - int count; // num of points - Evas_Coord_Rectangle normal_geometry; // bounding box of map geom actually - void *surface; // surface holding map if needed - int surface_w, surface_h; // current surface w & h alloc - Evas_Coord mx, my; // mouse x, y after conversion to map space - Eina_Bool alpha : 1; - Eina_Bool smooth : 1; - Evas_Map_Point points[]; // actual points + int count; // num of points + Evas_Coord_Rectangle normal_geometry; // bounding box of map geom actually + void *surface; // surface holding map if needed + int surface_w, surface_h; // current surface w & h alloc + Evas_Coord mx, my; // mouse x, y after conversion to map space + struct { + Evas_Coord px, py, z0, foc; + } persp; + Eina_Bool alpha : 1; + Eina_Bool smooth : 1; + Evas_Map_Point points[]; // actual points }; struct _Evas_Object diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h b/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h index 9c82e60b07..d5c858e740 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h @@ -139,9 +139,11 @@ struct _Evas_GL_Shared #define MAX_CUTOUT 512 #define DEF_CUTOUT 512 +// FIXME bug with pipes > 1 right now, should default to 32 #define MAX_PIPES 128 -#define DEF_PIPES 32 -#define DEF_PIPES_SGX_540 32 +#define DEF_PIPES 1 +//#define DEF_PIPES_SGX_540 32 +#define DEF_PIPES_SGX_540 1 #define DEF_PIPES_TEGRA_2 1 #define MIN_ATLAS_ALLOC 16 @@ -198,6 +200,9 @@ struct _Evas_GL_Shared int references; int w, h; int rot; + // persp map + int foc, z0, px, py; + int ax, ay; }; #define RTYPE_RECT 1 @@ -213,7 +218,8 @@ struct _Evas_GL_Context int references; int w, h; int rot; - RGBA_Draw_Context *dc; + int foc, z0, px, py; + RGBA_Draw_Context *dc; Evas_GL_Shared *shared; diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c b/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c index a1dccc9d5a..aeb5456f9e 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c @@ -133,72 +133,36 @@ glerr(int err, const char *file, const char *func, int line, const char *op) } static void -matrix_ident(GLfloat *m) -{ - memset(m, 0, 16 * sizeof(GLfloat)); - m[0] = m[5] = m[10] = m[15] = 1.0; - //------------------------ - // 1 0 0 0 - // 0 1 0 0 - // 0 0 1 0 - // 0 0 0 1 -} - -static void -matrix_ortho(GLfloat *m, - GLfloat l, GLfloat r, - GLfloat t, GLfloat b, +matrix_ortho(GLfloat *m, + GLfloat l, GLfloat r, + GLfloat t, GLfloat b, GLfloat near, GLfloat far, - int rot, int w, int h) + int rot, int vw, int vh, + int foc, GLfloat orth) { GLfloat rotf; GLfloat cosv, sinv; GLfloat tx, ty; -// rot = 180; - //------------------------ - m[0] = 2.0 / (r - l); - m[1] = 0.0; - m[2] = 0.0; - m[3] = 0.0; - - //------------------------ - m[4] = 0.0; - m[5] = 2.0 / (t - b); - m[6] = 0.0; - m[7] = 0.0; - - //------------------------ - m[8] = 0.0; - m[9] = 0.0; - m[10] = -(2.0 / (far - near)); - m[11] = 0.0; - - //------------------------ - m[12] = -((r + l) / (r - l)); - m[13] = -((t + b) / (t - b)); - m[14] = -((near + far) / (far - near)); - m[15] = 1.0; - - // rot rotf = (((rot / 90) & 0x3) * M_PI) / 2.0; - - tx = 0.0; - ty = 0.0; + + tx = -0.5 * (1.0 - orth); + ty = -0.5 * (1.0 - orth); + if (rot == 90) { - tx = -(w * 1.0); - ty = -(h * 0.0); + tx += -(vw * 1.0); + ty += -(vh * 0.0); } if (rot == 180) { - tx = -(w * 1.0); - ty = -(h * 1.0); + tx += -(vw * 1.0); + ty += -(vh * 1.0); } if (rot == 270) { - tx = -(w * 0.0); - ty = -(h * 1.0); + tx += -(vw * 0.0); + ty += -(vh * 1.0); } cosv = cos(rotf); @@ -206,14 +170,23 @@ matrix_ortho(GLfloat *m, m[0] = (2.0 / (r - l)) * ( cosv); m[1] = (2.0 / (r - l)) * ( sinv); + m[2] = 0.0; + m[3] = 0.0; m[4] = (2.0 / (t - b)) * (-sinv); m[5] = (2.0 / (t - b)) * ( cosv); + m[6] = 0.0; + m[7] = 0.0; - m[12] += (m[0] * tx) + (m[4] * ty); - m[13] += (m[1] * tx) + (m[5] * ty); - m[14] += (m[2] * tx) + (m[6] * ty); - m[15] += (m[3] * tx) + (m[7] * ty); + m[8] = 0.0; + m[9] = 0.0; + m[10] = -(2.0 / (far - near)); + m[11] = 1.0 / (GLfloat)foc; + + m[12] = (m[0] * tx) + (m[4] * ty) - ((r + l) / (r - l)); + m[13] = (m[1] * tx) + (m[5] * ty) - ((t + b) / (t - b)); + m[14] = (m[2] * tx) + (m[6] * ty) - ((near + far) / (far - near)); + m[15] = (m[3] * tx) + (m[7] * ty) + orth; } static int @@ -308,8 +281,9 @@ static void _evas_gl_common_viewport_set(Evas_GL_Context *gc) { GLfloat proj[16]; - int w = 1, h = 1, m = 1, rot = 1; + int w = 1, h = 1, m = 1, rot = 1, foc = 0; + foc = gc->foc; // surface in pipe 0 will be the same as all pipes if ((gc->pipe[0].shader.surface == gc->def_surface) || (!gc->pipe[0].shader.surface)) @@ -328,23 +302,100 @@ _evas_gl_common_viewport_set(Evas_GL_Context *gc) if ((!gc->change.size) || ((gc->shared->w == w) && (gc->shared->h == h) && - (gc->shared->rot == rot))) + (gc->shared->rot == rot) && (gc->shared->foc == gc->foc))) return; gc->shared->w = w; gc->shared->h = h; gc->shared->rot = rot; + gc->shared->foc = foc; + gc->shared->z0 = gc->z0; + gc->shared->px = gc->px; + gc->shared->py = gc->py; gc->change.size = 0; - if ((rot == 0) || (rot == 180)) - glViewport(0, 0, w, h); + if (foc == 0) + { + if ((rot == 0) || (rot == 180)) + glViewport(0, 0, w, h); + else + glViewport(0, 0, h, w); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + // std matrix + if (m == 1) + matrix_ortho(proj, + 0, w, 0, h, + -1000000.0, 1000000.0, + rot, w, h, + 1, 1.0); + // v flipped matrix for render-to-texture + else + matrix_ortho(proj, + 0, w, h, 0, + -1000000.0, 1000000.0, + rot, w, h, + 1, 1.0); + } else - glViewport(0, 0, h, w); - GLERR(__FUNCTION__, __FILE__, __LINE__, ""); - - matrix_ident(proj); - if (m == 1) matrix_ortho(proj, 0, w, 0, h, -1.0, 1.0, rot, w, h); - else matrix_ortho(proj, 0, w, h, 0, -1.0, 1.0, rot, w, h); + { + int px, py, vx, vy, vw = 0, vh = 0, ax = 0, ay = 0, ppx = 0, ppy = 0; + + px = gc->shared->px; + py = gc->shared->py; + + if ((rot == 0 ) || (rot == 90 )) ppx = px; + else if ((rot == 180) || (rot == 270)) ppx = w - px; + if ((rot == 0 ) || (rot == 270)) ppy = py; + else if ((rot == 90 ) || (rot == 180)) ppy = h - py; + + vx = ((w / 2) - ppx); + if (vx >= 0) + { + vw = w + (2 * vx); + if ((rot == 0 ) || (rot == 90 )) ax = 2 * vx; + else if ((rot == 180) || (rot == 270)) ax = 0; + } + else + { + vw = w - (2 * vx); + if ((rot == 0 ) || (rot == 90 )) ax = 0; + else if ((rot == 180) || (rot == 270)) ax = ppx - px; + vx = 0; + } + + vy = ((h / 2) - ppy); + if (vy < 0) + { + vh = h - (2 * vy); + if ((rot == 0 )) ay = 0; + else if ((rot == 90 ) || (rot == 180) || (rot == 270)) ay = ppy - py; + vy = -vy; + } + else + { + vh = h + (2 * vy); + if ((rot == 0 ) || (rot == 270)) ay = 2 * vy; + else if ((rot == 90 ) || (rot == 180)) ay = 0; + vy = 0; + } + + if ((rot == 0) || (rot == 180)) + glViewport(-2 * vx, -2 * vy, vw, vh); + else + glViewport(-2 * vy, -2 * vx, vh, vw); + if (m == 1) + matrix_ortho(proj, 0, vw, 0, vh, + -1000000.0, 1000000.0, + rot, vw, vh, + foc, 0.0); + else + matrix_ortho(proj, 0, vw, vh, 0, + -1000000.0, 1000000.0, + rot, vw, vh, + foc, 0.0); + gc->shared->ax = ax; + gc->shared->ay = ay; + } glUseProgram(gc->shared->shader.rect.prog); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); @@ -1812,7 +1863,6 @@ again: } } -// FIXME: we don't handle clipped maps right :( void evas_gl_common_context_image_map4_push(Evas_GL_Context *gc, Evas_GL_Texture *tex, @@ -1830,6 +1880,7 @@ evas_gl_common_context_image_map4_push(Evas_GL_Context *gc, DATA32 cmul; GLuint prog = gc->shared->shader.img.prog; int pn = 0; + int flat = 0; if (!tex->alpha) blend = 0; if (a < 255) blend = 1; @@ -1837,6 +1888,13 @@ evas_gl_common_context_image_map4_push(Evas_GL_Context *gc, (A_VAL(&(p[2].col)) < 0xff) || (A_VAL(&(p[3].col)) < 0xff)) blend = 1; + if ((p[0].z == p[1].z) && (p[1].z == p[2].z) && (p[2].z == p[3].z)) + flat = 1; + + if (!flat) + { + if (p[0].foc <= 0) flat = 1; + } if (yuv) { prog = gc->shared->shader.yuv.prog; @@ -1913,7 +1971,16 @@ evas_gl_common_context_image_map4_push(Evas_GL_Context *gc, } } -// /*xxx*/ shader_array_flush(gc); + if (!flat) + { + shader_array_flush(gc); + gc->foc = p[0].foc >> FP; + gc->z0 = p[0].z0 >> FP; + gc->px = p[0].px >> FP; + gc->py = p[0].py >> FP; + gc->change.size = 1; + _evas_gl_common_viewport_set(gc); + } again: vertex_array_size_check(gc, gc->state.top_pipe, 6); pn = gc->state.top_pipe; @@ -2137,10 +2204,21 @@ again: for (i = 0; i < 6; i++) { DATA32 cl = MUL4_SYM(cmul, p[points[i]].col); - PUSH_VERTEX(pn, - (p[points[i]].x >> FP), - (p[points[i]].y >> FP), - 0); + if (flat) + { + PUSH_VERTEX(pn, + (p[points[i]].x >> FP), + (p[points[i]].y >> FP), + 0); + } + else + { + PUSH_VERTEX(pn, + (p[points[i]].x3 >> FP) + gc->shared->ax, + (p[points[i]].y3 >> FP) + gc->shared->ay, + (p[points[i]].z >> FP) + + (gc->shared->foc - gc->shared->z0)); + } PUSH_TEXUV(pn, tx[points[i]], ty[points[i]]); @@ -2160,6 +2238,16 @@ again: B_VAL(&cl), A_VAL(&cl)); } + if (!flat) + { + shader_array_flush(gc); + gc->foc = 0; + gc->z0 = 0; + gc->px = 0; + gc->py = 0; + gc->change.size = 1; + _evas_gl_common_viewport_set(gc); + } } void