brutally evil... internally.. but it works. map perspective correct

now in gl engine. hooray for that. one complaint less.



SVN revision: 52566
This commit is contained in:
Carsten Haitzler 2010-09-22 06:52:28 +00:00
parent 787b09464b
commit 011b2ce822
7 changed files with 222 additions and 87 deletions

View File

@ -73,6 +73,7 @@ _evas_map_new(int count)
Evas_Map *m = calloc(1, sizeof(Evas_Map) + count * sizeof(Evas_Map_Point)); Evas_Map *m = calloc(1, sizeof(Evas_Map) + count * sizeof(Evas_Map_Point));
if (!m) return NULL; if (!m) return NULL;
m->count = count; m->count = count;
m->persp.foc = 0;
m->alpha = 1; m->alpha = 1;
m->smooth = 1; m->smooth = 1;
for (i = 0; i < count; i++) 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)); memcpy(dst->points, src->points, src->count * sizeof(Evas_Map_Point));
dst->smooth = src->smooth; dst->smooth = src->smooth;
dst->alpha = src->alpha; dst->alpha = src->alpha;
dst->persp = src->persp;
return EINA_TRUE; 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)); memcpy(copy->points, orig->points, orig->count * sizeof(Evas_Map_Point));
copy->smooth = orig->smooth; copy->smooth = orig->smooth;
copy->alpha = orig->alpha; copy->alpha = orig->alpha;
copy->persp = orig->persp;
return copy; 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 (!m) return;
if (idx >= m->count) return; if (idx >= m->count) return;
p = m->points + idx; p = m->points + idx;
p->x = x; p->x = p->px = x;
p->y = y; p->y = p->py = y;
p->z = z; 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].z = z;
p[3].u = 0.0; p[3].u = 0.0;
p[3].v = h; 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->x = x + cx;
p->y = y + cy; 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->x = x + cx;
p->y = y + cy; 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->x = x + cx;
p->y = y + cy; p->y = y + cy;
p->z = z + cz; 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 * Apply a perspective transform to the map
* *
* This applies a given perspective (3D) to the map coordinates. X, Y and Z * 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 * 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 * 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 = m->points;
p_end = p + m->count; 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++) for (; p < p_end; p++)
{ {
Evas_Coord x, y, zz; Evas_Coord x, y, zz;

View File

@ -2442,13 +2442,19 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su
p = obj->cur.map->points; p = obj->cur.map->points;
p_end = p + 4; p_end = p + 4;
pt = pts; 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 // draw geom +x +y
for (; p < p_end; p++, pt++) for (; p < p_end; p++, pt++)
{ {
pt->x = (p->x + x) << FP; pt->x = (p->x + x) << FP;
pt->y = (p->y + y) << FP; pt->y = (p->y + y) << FP;
pt->z = (p->z) << FP; pt->z = (p->z) << FP;
pt->x3 = p->px << FP;
pt->y3 = p->py << FP;
pt->u = p->u * FP1; pt->u = p->u * FP1;
pt->v = p->v * FP1; pt->v = p->v * FP1;
pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b); pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);

View File

@ -655,6 +655,11 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
return clean_them; 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 = obj->cur.map->points;
p_end = p + 4; p_end = p + 4;
pt = pts; 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->x = (p->x + off_x) << FP;
pt->y = (p->y + off_y) << FP; pt->y = (p->y + off_y) << FP;
pt->z = (p->z) << FP; pt->z = (p->z) << FP;
pt->x3 = p->px << FP;
pt->y3 = p->py << FP;
pt->u = p->u * FP1; pt->u = p->u * FP1;
pt->v = p->v * FP1; pt->v = p->v * FP1;
pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b); pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);

View File

@ -766,9 +766,12 @@ struct _RGBA_Polygon_Point
struct _RGBA_Map_Point struct _RGBA_Map_Point
{ {
FPc x, y; // x, y screenspace FPc x, y; // x, y screenspace
FPc x3, y3; // x, y 3d space
FPc z; // z in world space. optional FPc z; // z in world space. optional
FPc u, v; // u, v in tex coords FPc u, v; // u, v in tex coords
DATA32 col; // color at this point DATA32 col; // color at this point
// for perspective correctness - only point 0 has relevant info
FPc px, py, z0, foc;
}; };
// for fonts... // for fonts...

View File

@ -362,21 +362,24 @@ struct _Evas_Size_Hints
struct _Evas_Map_Point struct _Evas_Map_Point
{ {
Evas_Coord x, y, z; Evas_Coord x, y, z, px, py;
double u, v; double u, v;
unsigned char r, g, b, a; unsigned char r, g, b, a;
}; };
struct _Evas_Map struct _Evas_Map
{ {
int count; // num of points int count; // num of points
Evas_Coord_Rectangle normal_geometry; // bounding box of map geom actually Evas_Coord_Rectangle normal_geometry; // bounding box of map geom actually
void *surface; // surface holding map if needed void *surface; // surface holding map if needed
int surface_w, surface_h; // current surface w & h alloc int surface_w, surface_h; // current surface w & h alloc
Evas_Coord mx, my; // mouse x, y after conversion to map space Evas_Coord mx, my; // mouse x, y after conversion to map space
Eina_Bool alpha : 1; struct {
Eina_Bool smooth : 1; Evas_Coord px, py, z0, foc;
Evas_Map_Point points[]; // actual points } persp;
Eina_Bool alpha : 1;
Eina_Bool smooth : 1;
Evas_Map_Point points[]; // actual points
}; };
struct _Evas_Object struct _Evas_Object

View File

@ -139,9 +139,11 @@ struct _Evas_GL_Shared
#define MAX_CUTOUT 512 #define MAX_CUTOUT 512
#define DEF_CUTOUT 512 #define DEF_CUTOUT 512
// FIXME bug with pipes > 1 right now, should default to 32
#define MAX_PIPES 128 #define MAX_PIPES 128
#define DEF_PIPES 32 #define DEF_PIPES 1
#define DEF_PIPES_SGX_540 32 //#define DEF_PIPES_SGX_540 32
#define DEF_PIPES_SGX_540 1
#define DEF_PIPES_TEGRA_2 1 #define DEF_PIPES_TEGRA_2 1
#define MIN_ATLAS_ALLOC 16 #define MIN_ATLAS_ALLOC 16
@ -198,6 +200,9 @@ struct _Evas_GL_Shared
int references; int references;
int w, h; int w, h;
int rot; int rot;
// persp map
int foc, z0, px, py;
int ax, ay;
}; };
#define RTYPE_RECT 1 #define RTYPE_RECT 1
@ -213,7 +218,8 @@ struct _Evas_GL_Context
int references; int references;
int w, h; int w, h;
int rot; int rot;
RGBA_Draw_Context *dc; int foc, z0, px, py;
RGBA_Draw_Context *dc;
Evas_GL_Shared *shared; Evas_GL_Shared *shared;

View File

@ -133,72 +133,36 @@ glerr(int err, const char *file, const char *func, int line, const char *op)
} }
static void static void
matrix_ident(GLfloat *m) matrix_ortho(GLfloat *m,
{ GLfloat l, GLfloat r,
memset(m, 0, 16 * sizeof(GLfloat)); GLfloat t, GLfloat b,
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,
GLfloat near, GLfloat far, GLfloat near, GLfloat far,
int rot, int w, int h) int rot, int vw, int vh,
int foc, GLfloat orth)
{ {
GLfloat rotf; GLfloat rotf;
GLfloat cosv, sinv; GLfloat cosv, sinv;
GLfloat tx, ty; 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; rotf = (((rot / 90) & 0x3) * M_PI) / 2.0;
tx = 0.0; tx = -0.5 * (1.0 - orth);
ty = 0.0; ty = -0.5 * (1.0 - orth);
if (rot == 90) if (rot == 90)
{ {
tx = -(w * 1.0); tx += -(vw * 1.0);
ty = -(h * 0.0); ty += -(vh * 0.0);
} }
if (rot == 180) if (rot == 180)
{ {
tx = -(w * 1.0); tx += -(vw * 1.0);
ty = -(h * 1.0); ty += -(vh * 1.0);
} }
if (rot == 270) if (rot == 270)
{ {
tx = -(w * 0.0); tx += -(vw * 0.0);
ty = -(h * 1.0); ty += -(vh * 1.0);
} }
cosv = cos(rotf); cosv = cos(rotf);
@ -206,14 +170,23 @@ matrix_ortho(GLfloat *m,
m[0] = (2.0 / (r - l)) * ( cosv); m[0] = (2.0 / (r - l)) * ( cosv);
m[1] = (2.0 / (r - l)) * ( sinv); m[1] = (2.0 / (r - l)) * ( sinv);
m[2] = 0.0;
m[3] = 0.0;
m[4] = (2.0 / (t - b)) * (-sinv); m[4] = (2.0 / (t - b)) * (-sinv);
m[5] = (2.0 / (t - b)) * ( cosv); m[5] = (2.0 / (t - b)) * ( cosv);
m[6] = 0.0;
m[7] = 0.0;
m[12] += (m[0] * tx) + (m[4] * ty); m[8] = 0.0;
m[13] += (m[1] * tx) + (m[5] * ty); m[9] = 0.0;
m[14] += (m[2] * tx) + (m[6] * ty); m[10] = -(2.0 / (far - near));
m[15] += (m[3] * tx) + (m[7] * ty); 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 static int
@ -308,8 +281,9 @@ static void
_evas_gl_common_viewport_set(Evas_GL_Context *gc) _evas_gl_common_viewport_set(Evas_GL_Context *gc)
{ {
GLfloat proj[16]; 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 // surface in pipe 0 will be the same as all pipes
if ((gc->pipe[0].shader.surface == gc->def_surface) || if ((gc->pipe[0].shader.surface == gc->def_surface) ||
(!gc->pipe[0].shader.surface)) (!gc->pipe[0].shader.surface))
@ -328,23 +302,100 @@ _evas_gl_common_viewport_set(Evas_GL_Context *gc)
if ((!gc->change.size) || if ((!gc->change.size) ||
((gc->shared->w == w) && (gc->shared->h == h) && ((gc->shared->w == w) && (gc->shared->h == h) &&
(gc->shared->rot == rot))) (gc->shared->rot == rot) && (gc->shared->foc == gc->foc)))
return; return;
gc->shared->w = w; gc->shared->w = w;
gc->shared->h = h; gc->shared->h = h;
gc->shared->rot = rot; 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; gc->change.size = 0;
if ((rot == 0) || (rot == 180)) if (foc == 0)
glViewport(0, 0, w, h); {
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 else
glViewport(0, 0, h, w); {
GLERR(__FUNCTION__, __FILE__, __LINE__, ""); int px, py, vx, vy, vw = 0, vh = 0, ax = 0, ay = 0, ppx = 0, ppy = 0;
matrix_ident(proj); px = gc->shared->px;
if (m == 1) matrix_ortho(proj, 0, w, 0, h, -1.0, 1.0, rot, w, h); py = gc->shared->py;
else matrix_ortho(proj, 0, w, h, 0, -1.0, 1.0, rot, w, h);
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); glUseProgram(gc->shared->shader.rect.prog);
GLERR(__FUNCTION__, __FILE__, __LINE__, ""); GLERR(__FUNCTION__, __FILE__, __LINE__, "");
@ -1812,7 +1863,6 @@ again:
} }
} }
// FIXME: we don't handle clipped maps right :(
void void
evas_gl_common_context_image_map4_push(Evas_GL_Context *gc, evas_gl_common_context_image_map4_push(Evas_GL_Context *gc,
Evas_GL_Texture *tex, Evas_GL_Texture *tex,
@ -1830,6 +1880,7 @@ evas_gl_common_context_image_map4_push(Evas_GL_Context *gc,
DATA32 cmul; DATA32 cmul;
GLuint prog = gc->shared->shader.img.prog; GLuint prog = gc->shared->shader.img.prog;
int pn = 0; int pn = 0;
int flat = 0;
if (!tex->alpha) blend = 0; if (!tex->alpha) blend = 0;
if (a < 255) blend = 1; 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)) (A_VAL(&(p[2].col)) < 0xff) || (A_VAL(&(p[3].col)) < 0xff))
blend = 1; 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) if (yuv)
{ {
prog = gc->shared->shader.yuv.prog; 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: again:
vertex_array_size_check(gc, gc->state.top_pipe, 6); vertex_array_size_check(gc, gc->state.top_pipe, 6);
pn = gc->state.top_pipe; pn = gc->state.top_pipe;
@ -2137,10 +2204,21 @@ again:
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
{ {
DATA32 cl = MUL4_SYM(cmul, p[points[i]].col); DATA32 cl = MUL4_SYM(cmul, p[points[i]].col);
PUSH_VERTEX(pn, if (flat)
(p[points[i]].x >> FP), {
(p[points[i]].y >> FP), PUSH_VERTEX(pn,
0); (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, PUSH_TEXUV(pn,
tx[points[i]], tx[points[i]],
ty[points[i]]); ty[points[i]]);
@ -2160,6 +2238,16 @@ again:
B_VAL(&cl), B_VAL(&cl),
A_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 void