Move the get_actor_at_pos() inside ClutterStage, as it is pure

GL and not GLX. Removed the get_actor_at_pos() and flush() vfuncs
from ClutterStageClass: clutter_stage_flush() becomes the private
_clutter_stage_sync_viewport() function, which should only be used
internally.
This commit is contained in:
Emmanuele Bassi 2007-03-25 11:47:30 +00:00
parent 65d1a65b49
commit fa93634d14
5 changed files with 142 additions and 160 deletions

View File

@ -137,6 +137,8 @@ void _clutter_synthetise_stage_state (ClutterBackend *backend,
ClutterStageState set_flags, ClutterStageState set_flags,
ClutterStageState unset_flags); ClutterStageState unset_flags);
void _clutter_stage_sync_viewport (ClutterStage *stage);
G_END_DECLS G_END_DECLS
#endif /* _HAVE_CLUTTER_PRIVATE_H */ #endif /* _HAVE_CLUTTER_PRIVATE_H */

View File

@ -44,6 +44,8 @@
#include "clutter-debug.h" #include "clutter-debug.h"
#include "clutter-version.h" /* For flavour */ #include "clutter-version.h" /* For flavour */
#include <GL/gl.h>
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h> #include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
G_DEFINE_ABSTRACT_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP); G_DEFINE_ABSTRACT_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP);
@ -581,23 +583,6 @@ clutter_stage_hide_cursor (ClutterStage *stage)
} }
} }
/**
* clutter_stage_flush:
* @stage: a #ClutterStage
*
* Flushes the stage. This function is only useful for stage
* implementations inside backends or for actors; you should never
* need to call this function directly.
*/
void
clutter_stage_flush (ClutterStage *stage)
{
g_return_if_fail (CLUTTER_IS_STAGE (stage));
if (CLUTTER_STAGE_GET_CLASS (stage)->flush)
CLUTTER_STAGE_GET_CLASS (stage)->flush (stage);
}
/** /**
* clutter_stage_snapshot * clutter_stage_snapshot
* @stage: A #ClutterStage * @stage: A #ClutterStage
@ -637,17 +622,148 @@ clutter_stage_snapshot (ClutterStage *stage,
return NULL; return NULL;
} }
static inline void
frustum (GLfloat left,
GLfloat right,
GLfloat bottom,
GLfloat top,
GLfloat nearval,
GLfloat farval)
{
GLfloat x, y, a, b, c, d;
GLfloat m[16];
x = (2.0 * nearval) / (right - left);
y = (2.0 * nearval) / (top - bottom);
a = (right + left) / (right - left);
b = (top + bottom) / (top - bottom);
c = -(farval + nearval) / ( farval - nearval);
d = -(2.0 * farval * nearval) / (farval - nearval);
#define M(row,col) m[col*4+row]
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
#undef M
glMultMatrixf (m);
}
static inline void
perspective (GLfloat fovy,
GLfloat aspect,
GLfloat zNear,
GLfloat zFar)
{
GLfloat xmin, xmax, ymin, ymax;
ymax = zNear * tan (fovy * M_PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
frustum (xmin, xmax, ymin, ymax, zNear, zFar);
}
void
_clutter_stage_sync_viewport (ClutterStage *stage)
{
ClutterActor *actor;
gint width, height;
g_return_if_fail (CLUTTER_IS_STAGE (stage));
actor = CLUTTER_ACTOR (stage);
width = clutter_actor_get_width (actor);
height = clutter_actor_get_height (actor);
glViewport (0, 0, width, height);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
perspective (60.0f, 1.0f, 0.1f, 100.0f);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
/* Then for 2D like transform */
/* camera distance from screen, 0.5 * tan (FOV) */
#define DEFAULT_Z_CAMERA 0.866025404f
glTranslatef (-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
glScalef ( 1.0f / width,
-1.0f / height,
1.0f / width);
glTranslatef (0.0f, -1.0 * height, 0.0f);
}
/**
* clutter_stage_get_actor_at_pos:
* @stage:
* @x:
* @y:
*
* FIXME
*
* Return value: the actor at the specified coordinates, if any
*/
ClutterActor * ClutterActor *
clutter_stage_get_actor_at_pos (ClutterStage *stage, clutter_stage_get_actor_at_pos (ClutterStage *stage,
gint x, gint x,
gint y) gint y)
{ {
ClutterActor *found = NULL;
GLuint buff[64] = { 0 };
GLint hits;
GLint view[4];
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
if (CLUTTER_STAGE_GET_CLASS (stage)->get_actor_at_pos) glSelectBuffer (sizeof (buff), buff);
glGetIntegerv (GL_VIEWPORT, view);
glRenderMode (GL_SELECT);
glInitNames ();
glPushName (0);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
/* This is gluPickMatrix(x, y, 1.0, 1.0, view); */
glTranslatef ((view[2] - 2 * (x - view[0])),
(view[3] - 2 * (y - view[1])), 0);
glScalef (view[2], -view[3], 1.0);
perspective (60.0f, 1.0f, 0.1f, 100.0f);
glMatrixMode (GL_MODELVIEW);
clutter_actor_paint (CLUTTER_ACTOR (stage));
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
hits = glRenderMode (GL_RENDER);
if (hits != 0)
{ {
return CLUTTER_STAGE_GET_CLASS (stage)->get_actor_at_pos (stage, x, y); #if 0
gint i
for (i = 0; i < hits; i++)
g_print ("Hit at %i\n", buff[i * 4 + 3]);
#endif
found = clutter_group_find_child_by_id (CLUTTER_GROUP (stage),
buff[(hits-1) * 4 + 3]);
} }
return NULL; _clutter_stage_sync_viewport (stage);
return found;
} }

View File

@ -84,9 +84,6 @@ struct _ClutterStageClass
gboolean visible); gboolean visible);
void (* set_offscreen) (ClutterStage *stage, void (* set_offscreen) (ClutterStage *stage,
gboolean offscreen); gboolean offscreen);
ClutterActor *(* get_actor_at_pos) (ClutterStage *stage,
gint x,
gint y);
void (* draw_to_pixbuf) (ClutterStage *stage, void (* draw_to_pixbuf) (ClutterStage *stage,
GdkPixbuf *dest, GdkPixbuf *dest,
gint x, gint x,

View File

@ -45,75 +45,6 @@
G_DEFINE_TYPE (ClutterStageGlx, clutter_stage_glx, CLUTTER_TYPE_STAGE); G_DEFINE_TYPE (ClutterStageGlx, clutter_stage_glx, CLUTTER_TYPE_STAGE);
static inline void
frustum (GLfloat left,
GLfloat right,
GLfloat bottom,
GLfloat top,
GLfloat nearval,
GLfloat farval)
{
GLfloat x, y, a, b, c, d;
GLfloat m[16];
x = (2.0 * nearval) / (right - left);
y = (2.0 * nearval) / (top - bottom);
a = (right + left) / (right - left);
b = (top + bottom) / (top - bottom);
c = -(farval + nearval) / ( farval - nearval);
d = -(2.0 * farval * nearval) / (farval - nearval);
#define M(row,col) m[col*4+row]
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
#undef M
glMultMatrixf (m);
}
static inline void
perspective (GLfloat fovy,
GLfloat aspect,
GLfloat zNear,
GLfloat zFar)
{
GLfloat xmin, xmax, ymin, ymax;
ymax = zNear * tan (fovy * M_PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
frustum (xmin, xmax, ymin, ymax, zNear, zFar);
}
static void
sync_viewport (ClutterStageGlx *stage_glx)
{
glViewport (0, 0, stage_glx->xwin_width, stage_glx->xwin_height);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
perspective (60.0f, 1.0f, 0.1f, 100.0f);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
/* Then for 2D like transform */
/* camera distance from screen, 0.5 * tan (FOV) */
#define DEFAULT_Z_CAMERA 0.866025404f
glTranslatef (-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
glScalef ( 1.0f / stage_glx->xwin_width,
-1.0f / stage_glx->xwin_height,
1.0f / stage_glx->xwin_width);
glTranslatef (0.0f, -1.0 * stage_glx->xwin_height, 0.0f);
}
static void static void
clutter_stage_glx_show (ClutterActor *actor) clutter_stage_glx_show (ClutterActor *actor)
{ {
@ -349,7 +280,7 @@ clutter_stage_glx_realize (ClutterActor *actor)
glXIsDirect (stage_glx->xdpy, stage_glx->gl_context) ? "yes" glXIsDirect (stage_glx->xdpy, stage_glx->gl_context) ? "yes"
: "no"); : "no");
sync_viewport (stage_glx); _clutter_stage_sync_viewport (CLUTTER_STAGE (stage_glx));
} }
static void static void
@ -449,7 +380,7 @@ clutter_stage_glx_request_coords (ClutterActor *self,
clutter_actor_realize (self); clutter_actor_realize (self);
} }
sync_viewport (stage_glx); _clutter_stage_sync_viewport (CLUTTER_STAGE (stage_glx));
} }
if (stage_glx->xwin != None) /* Do we want to bother ? */ if (stage_glx->xwin != None) /* Do we want to bother ? */
@ -493,7 +424,7 @@ clutter_stage_glx_set_fullscreen (ClutterStage *stage,
XDeleteProperty (stage_glx->xdpy, stage_glx->xwin, atom_WM_STATE); XDeleteProperty (stage_glx->xdpy, stage_glx->xwin, atom_WM_STATE);
} }
sync_viewport (stage_glx); _clutter_stage_sync_viewport (stage);
} }
static void static void
@ -537,7 +468,7 @@ clutter_stage_glx_set_cursor_visible (ClutterStage *stage,
#endif /* HAVE_XFIXES */ #endif /* HAVE_XFIXES */
} }
sync_viewport (stage_glx); _clutter_stage_sync_viewport (stage);
} }
static void static void
@ -547,61 +478,6 @@ clutter_stage_glx_set_offscreen (ClutterStage *stage,
} }
static ClutterActor *
clutter_stage_glx_get_actor_at_pos (ClutterStage *stage,
gint x,
gint y)
{
ClutterActor *found = NULL;
GLuint buff[64] = { 0 };
GLint hits;
GLint view[4];
glSelectBuffer (sizeof (buff), buff);
glGetIntegerv (GL_VIEWPORT, view);
glRenderMode (GL_SELECT);
glInitNames ();
glPushName (0);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
/* This is gluPickMatrix(x, y, 1.0, 1.0, view); */
glTranslatef ((view[2] - 2 * (x - view[0])),
(view[3] - 2 * (y - view[1])), 0);
glScalef (view[2], -view[3], 1.0);
perspective (60.0f, 1.0f, 0.1f, 100.0f);
glMatrixMode (GL_MODELVIEW);
clutter_actor_paint (CLUTTER_ACTOR (stage));
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
hits = glRenderMode(GL_RENDER);
if (hits != 0)
{
#if 0
gint i
for (i = 0; i < hits; i++)
g_print ("Hit at %i\n", buff[i * 4 + 3]);
#endif
found = clutter_group_find_child_by_id (CLUTTER_GROUP (stage),
buff[(hits-1) * 4 + 3]);
}
clutter_stage_flush (stage);
return found;
}
static void static void
snapshot_pixbuf_free (guchar *pixels, snapshot_pixbuf_free (guchar *pixels,
gpointer data) gpointer data)
@ -671,12 +547,6 @@ clutter_stage_glx_draw_to_pixbuf (ClutterStage *stage,
} }
} }
static void
clutter_stage_glx_flush (ClutterStage *stage)
{
sync_viewport (CLUTTER_STAGE_GLX (stage));
}
static void static void
clutter_stage_glx_dispose (GObject *gobject) clutter_stage_glx_dispose (GObject *gobject)
{ {
@ -708,9 +578,7 @@ clutter_stage_glx_class_init (ClutterStageGlxClass *klass)
stage_class->set_fullscreen = clutter_stage_glx_set_fullscreen; stage_class->set_fullscreen = clutter_stage_glx_set_fullscreen;
stage_class->set_cursor_visible = clutter_stage_glx_set_cursor_visible; stage_class->set_cursor_visible = clutter_stage_glx_set_cursor_visible;
stage_class->set_offscreen = clutter_stage_glx_set_offscreen; stage_class->set_offscreen = clutter_stage_glx_set_offscreen;
stage_class->get_actor_at_pos = clutter_stage_glx_get_actor_at_pos;
stage_class->draw_to_pixbuf = clutter_stage_glx_draw_to_pixbuf; stage_class->draw_to_pixbuf = clutter_stage_glx_draw_to_pixbuf;
stage_class->flush = clutter_stage_glx_flush;
} }
static void static void

View File

@ -131,7 +131,6 @@ Macro evaluating to the height of the #ClutterStage
@set_fullscreen: @set_fullscreen:
@set_cursor_visible: @set_cursor_visible:
@set_offscreen: @set_offscreen:
@get_actor_at_pos:
@draw_to_pixbuf: @draw_to_pixbuf:
@flush: @flush:
@event: @event: