Add threaded loader

This commit is contained in:
Matthew Allum 2005-03-27 20:12:19 +00:00
parent a731e612b6
commit bc2e4f9b70
8 changed files with 257 additions and 94 deletions

View File

@ -1,3 +1,18 @@
2005-03-27 mallum,,, <mallum@openedhand.com>
* Makefile:
* cltr-photo-grid.c: (cltr_photo_grid_cell_new),
(ctrl_photo_grid_get_zoomed_coords), (cltr_photo_grid_navigate),
(cltr_photo_grid_activate_cell), (cltr_photo_grid_populate),
(cltr_photo_grid_redraw), (cltr_photo_grid_new):
* cltr-photo-grid.h:
* cltr.c: (cltr_dispatch_x_event), (cltr_init), (test_idle_cb),
(main):
* cltr.h:
Add a very hacky threaded image loader.
* pixbuf.c: (pixel_set_vals), pixbuf.h:
Add copy func ( unused as yet )
2005-03-25 mallum,,, <mallum@openedhand.com>
* cltr-photo-grid.c: (cltr_photo_grid_cell_new),

View File

@ -1,5 +1,5 @@
LIBS=-lpng -lGL -ljpeg -L/usr/X11R6/lib -lX11 `pkg-config --libs pangoft2 pango glib-2.0`
CFLAGS=`pkg-config --cflags pangoft2 pango glib-2.0`
LIBS=-lpng -lGL -ljpeg -L/usr/X11R6/lib -lX11 `pkg-config --libs pangoft2 pango glib-2.0 gthread-2.0`
CFLAGS=`pkg-config --cflags pangoft2 pango glib-2.0 gthread-2.0`
.c.o:
$(CC) -g -Wall $(CFLAGS) $(INCS) -c $*.c

View File

@ -1,5 +1,8 @@
#include "cltr-photo-grid.h"
/* this likely shouldn'y go here */
static GMutex *Mutex_GRID = NULL;
ClutterPhotoGridCell*
cltr_photo_grid_cell_new(ClutterPhotoGrid *grid,
Pixbuf *pixb,
@ -39,6 +42,9 @@ cltr_photo_grid_cell_new(ClutterPhotoGrid *grid,
cell->angle = 6.0 - (rand()%12);
cell->anim_step = 15;
cell->state = CLTR_PHOTO_GRID_CELL_STATE_APPEARING;
return cell;
}
@ -83,6 +89,29 @@ ctrl_photo_grid_get_zoomed_coords(ClutterPhotoGrid *grid,
*ty = (float)grid->cell_height * (grid->zoom_max) * y * -1.0;
}
gboolean
cltr_photo_grid_idle_cb(gpointer data)
{
ClutterPhotoGrid *grid = (ClutterPhotoGrid *)data;
cltr_photo_grid_redraw(grid);
switch(grid->state)
{
case CLTR_PHOTO_GRID_STATE_LOADING:
case CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE:
case CLTR_PHOTO_GRID_STATE_ZOOM_IN:
case CLTR_PHOTO_GRID_STATE_ZOOM_OUT:
case CLTR_PHOTO_GRID_STATE_ZOOMED_MOVE:
return TRUE;
case CLTR_PHOTO_GRID_STATE_ZOOMED:
case CLTR_PHOTO_GRID_STATE_BROWSE:
default:
return FALSE; /* no need for rapid updates now */
}
}
void
cltr_photo_grid_navigate(ClutterPhotoGrid *grid,
CltrDirection direction)
@ -121,6 +150,8 @@ cltr_photo_grid_navigate(ClutterPhotoGrid *grid,
grid->view_min_y = grid->view_max_y ;
grid->anim_step = 0;
zoom = grid->zoom_max;
g_idle_add(cltr_photo_grid_idle_cb, grid);
}
ctrl_photo_grid_cell_to_coords(grid, grid->cell_active, &x, &y);
@ -130,6 +161,8 @@ cltr_photo_grid_navigate(ClutterPhotoGrid *grid,
&grid->view_max_y);
CLTR_DBG("x: %f, y: %f", grid->view_max_x , grid->view_max_y);
cltr_photo_grid_redraw(grid);
}
}
@ -139,6 +172,8 @@ cltr_photo_grid_activate_cell(ClutterPhotoGrid *grid)
if (grid->state == CLTR_PHOTO_GRID_STATE_BROWSE)
{
grid->state = CLTR_PHOTO_GRID_STATE_ZOOM_IN;
g_idle_add(cltr_photo_grid_idle_cb, grid);
}
else if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOMED)
{
@ -146,37 +181,53 @@ cltr_photo_grid_activate_cell(ClutterPhotoGrid *grid)
/* reset - zoomed moving will have reset */
grid->view_min_x = 0.0;
grid->view_min_y = 0.0;
g_idle_add(cltr_photo_grid_idle_cb, grid);
}
/* que a draw ? */
}
void
cltr_photo_grid_populate(ClutterPhotoGrid *grid,
const gchar *imgs_path)
gpointer
cltr_photo_grid_populate(gpointer data)
{
GDir *dir;
GError *error;
const gchar *entry = NULL;
gchar *fullpath = NULL;
int n_pixb = 0, i =0;
GList *cell_item;
ClutterFont *font = NULL;
ClutterPhotoGrid *grid = (ClutterPhotoGrid *)data;
GDir *dir;
GError *error;
const gchar *entry = NULL;
gchar *fullpath = NULL;
int n_pixb = 0, i =0;
ClutterFont *font = NULL;
font = font_new("Sans Bold 96");
if ((dir = g_dir_open (imgs_path, 0, &error)) == NULL)
if ((dir = g_dir_open (grid->img_path, 0, &error)) == NULL)
{
/* handle this much better */
fprintf(stderr, "failed to open '%s'\n", imgs_path);
return;
fprintf(stderr, "failed to open '%s'\n", grid->img_path);
return NULL;
}
while((entry = g_dir_read_name (dir)) != NULL)
while ((entry = g_dir_read_name (dir)) != NULL)
{
if (!strcasecmp(&entry[strlen(entry)-4], ".png")
|| !strcasecmp(&entry[strlen(entry)-4], ".jpg")
|| !strcasecmp(&entry[strlen(entry)-5], ".jpeg"))
n_pixb++;
}
CLTR_DBG("estamited %i pixb's\n", n_pixb);
grid->texs = util_malloc0(sizeof(GLuint)*n_pixb);
glGenTextures(n_pixb, grid->texs);
g_dir_rewind (dir);
while ((entry = g_dir_read_name (dir)) != NULL)
{
Pixbuf *pixb = NULL;
fullpath = g_strconcat(imgs_path, "/", entry, NULL);
fullpath = g_strconcat(grid->img_path, "/", entry, NULL);
pixb = pixbuf_new_from_file(fullpath);
@ -187,12 +238,47 @@ cltr_photo_grid_populate(ClutterPhotoGrid *grid,
cell = cltr_photo_grid_cell_new(grid, pixb, entry);
g_snprintf(&buf[0], 24, "%i", n_pixb);
g_snprintf(&buf[0], 24, "%i", i);
font_draw(font, cell->pixb, buf, 10, 10);
cell->texref = grid->texs[i];
g_mutex_lock(Mutex_GRID);
glBindTexture(GL_TEXTURE_2D, cell->texref);
CLTR_GLERR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
CLTR_GLERR();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
grid->tex_w,
grid->tex_h,
0, GL_RGBA,
GL_UNSIGNED_INT_8_8_8_8,
grid->tex_data);
CLTR_GLERR();
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0,
(GLsizei)cell->pixb->width,
(GLsizei)cell->pixb->height,
GL_RGBA, GL_UNSIGNED_INT_8_8_8_8,
cell->pixb->data);
CLTR_GLERR();
g_mutex_unlock(Mutex_GRID);
cltr_photo_grid_append_cell(grid, cell);
n_pixb++;
i++;
}
g_free(fullpath);
@ -200,49 +286,17 @@ cltr_photo_grid_populate(ClutterPhotoGrid *grid,
g_dir_close (dir);
g_mutex_lock(Mutex_GRID);
grid->cell_active = g_list_first(grid->cells_tail);
/* Set up textures */
grid->state = CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE;
grid->texs = util_malloc0(sizeof(GLuint)*n_pixb);
glGenTextures(n_pixb, grid->texs);
g_mutex_unlock(Mutex_GRID);
cell_item = g_list_first(grid->cells_tail);
cltr_photo_grid_redraw(grid);
do
{
ClutterPhotoGridCell *cell = (ClutterPhotoGridCell *)cell_item->data;
glBindTexture(GL_TEXTURE_2D, grid->texs[i]);
CLTR_DBG("loading texture %i", i);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
grid->tex_w,
grid->tex_h,
0, GL_RGBA,
GL_UNSIGNED_INT_8_8_8_8,
grid->tex_data);
CLTR_GLERR();
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0,
(GLsizei)cell->pixb->width,
(GLsizei)cell->pixb->height,
GL_RGBA, GL_UNSIGNED_INT_8_8_8_8,
cell->pixb->data);
CLTR_GLERR();
i++;
}
while ( (cell_item = g_list_next(cell_item)) != NULL );
return NULL;
}
void
@ -252,11 +306,21 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid)
GList *cell_item;
float zoom, trans_x, trans_y;
/* CLTR_MARK();*/
glPushMatrix();
glClear(GL_COLOR_BUFFER_BIT);
glClearColor( 0.6, 0.6, 0.62, 1.0);
if (grid->cells_tail == NULL)
{
glPopMatrix();
glXSwapBuffers(CltrCntx.xdpy, grid->parent->xwin);
return;
}
glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
@ -273,7 +337,9 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid)
trans_x = grid->view_min_x;
trans_y = grid->view_min_y;
if (grid->state != CLTR_PHOTO_GRID_STATE_BROWSE)
if (grid->state != CLTR_PHOTO_GRID_STATE_BROWSE
&& grid->state != CLTR_PHOTO_GRID_STATE_LOADING
&& grid->state != CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE)
{
/* Assume zoomed in */
zoom = grid->zoom_max;
@ -309,8 +375,9 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid)
{
zoom = grid->zoom_min;
grid->anim_step = 0;
trans_x = grid->view_min_x;
trans_y = grid->view_min_y;
grid->state = CLTR_PHOTO_GRID_STATE_BROWSE;
}
else
{
@ -320,12 +387,6 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid)
zoom = grid->zoom_min + (grid->zoom_max - grid->zoom_min) * f;
trans_x = (grid->view_max_x - grid->view_min_x) * f;
trans_y = (grid->view_max_y - grid->view_min_y) * f;
#if 0
zoom = grid->zoom_min
+ (( (grid->zoom_max - grid->zoom_min) / grid->anim_n_steps )
* (grid->anim_n_steps - grid->anim_step) );
#endif
}
}
else if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOMED_MOVE)
@ -372,6 +433,23 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid)
thumb_w = (pixb->width / grid->n_cols);
thumb_h = (pixb->height / grid->n_rows);
if (cell->state == CLTR_PHOTO_GRID_CELL_STATE_APPEARING)
{
cell->anim_step -= 4;
if (cell->anim_step <= 0)
{
cell->state = CLTR_PHOTO_GRID_CELL_STATE_STATIC;
}
else
{
thumb_w = thumb_w + cell->anim_step;
thumb_h = thumb_h + cell->anim_step;
}
cell->anim_step = 0;
}
ew_border = thumb_w/8;
ns_border = thumb_h/8;
@ -397,8 +475,9 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid)
/* Translate origin to rotation point ( photo center ) */
glTranslatef( x1 + ((x2-x1)/2), y1 + ((y2-y1)/2), 0.0);
/* Rotate around Z axis */
glRotatef ( cell->angle, 0.0, 0.0, 1.0);
if (cell->state != CLTR_PHOTO_GRID_CELL_STATE_APPEARING)
/* Rotate around Z axis */
glRotatef ( cell->angle, 0.0, 0.0, 1.0);
/* Border - why need tex disabled ? */
glDisable(GL_TEXTURE_2D);
@ -416,7 +495,9 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid)
glEnable(GL_TEXTURE_2D);
glEnable(GL_SMOOTH);
glBindTexture(GL_TEXTURE_2D, grid->texs[i]);
g_mutex_lock(Mutex_GRID);
glBindTexture(GL_TEXTURE_2D, cell->texref);
/*
if (cell == grid->cell_active
@ -440,6 +521,8 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid)
glEnd ();
}
g_mutex_unlock(Mutex_GRID);
/* back to regular non translated matrix */
glPopMatrix();
@ -471,18 +554,29 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid)
glXSwapBuffers(CltrCntx.xdpy, grid->parent->xwin);
g_mutex_lock(Mutex_GRID);
/* Hack, so final item get painted via threaded load */
if (grid->state == CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE)
grid->state = CLTR_PHOTO_GRID_STATE_BROWSE;
g_mutex_unlock(Mutex_GRID);
}
ClutterPhotoGrid*
cltr_photo_grid_new(ClutterWindow *win,
int n_cols,
int n_rows,
const gchar *imgs_path)
const gchar *img_path)
{
ClutterPhotoGrid *grid = NULL;
GThread *loader_thread;
grid = util_malloc0(sizeof(ClutterPhotoGrid));
grid->img_path = strdup(img_path);
grid->width = win->width;
grid->height = win->height;
grid->n_cols = n_cols;
@ -492,7 +586,7 @@ cltr_photo_grid_new(ClutterWindow *win,
grid->cell_width = grid->width / n_cols;
grid->cell_height = grid->height / n_rows;
grid->state = CLTR_PHOTO_GRID_STATE_BROWSE;
grid->state = CLTR_PHOTO_GRID_STATE_LOADING;
grid->anim_n_steps = 50; /* value needs to be calced dep on rows */
grid->anim_step = 0;
@ -516,10 +610,14 @@ cltr_photo_grid_new(ClutterWindow *win,
grid->tex_data = malloc (grid->tex_w * grid->tex_h * 4);
/* Load */
cltr_photo_grid_populate(grid, imgs_path);
Mutex_GRID = g_mutex_new();
grid->cell_active = g_list_first(grid->cells_tail);
/* Load */
loader_thread = g_thread_create (cltr_photo_grid_populate,
(gpointer)grid,
TRUE,
NULL);
/*
ctrl_photo_grid_cell_to_coords(grid, grid->cell_active, &x, &y);
@ -530,7 +628,8 @@ cltr_photo_grid_new(ClutterWindow *win,
&grid->view_max_x,
&grid->view_max_y);
*/
cltr_photo_grid_redraw(grid);
g_idle_add(cltr_photo_grid_idle_cb, grid);
return grid;
}

View File

@ -9,6 +9,8 @@ typedef struct ClutterPhotoGridCell ClutterPhotoGridCell;
typedef enum ClutterPhotoGridState
{
CLTR_PHOTO_GRID_STATE_LOADING ,
CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE ,
CLTR_PHOTO_GRID_STATE_BROWSE ,
CLTR_PHOTO_GRID_STATE_ZOOM_IN ,
CLTR_PHOTO_GRID_STATE_ZOOMED ,
@ -17,10 +19,23 @@ typedef enum ClutterPhotoGridState
}
ClutterPhotoGridState;
typedef enum ClutterPhotoGridCellState
{
CLTR_PHOTO_GRID_CELL_STATE_APPEARING,
CLTR_PHOTO_GRID_CELL_STATE_STATIC,
}
ClutterPhotoGridCellState;
struct ClutterPhotoGridCell
{
Pixbuf *pixb;
float angle;
GLuint texref;
gint anim_step;
ClutterPhotoGridCellState state;
};
struct ClutterPhotoGrid
@ -33,6 +48,8 @@ struct ClutterPhotoGrid
/* ****** */
gchar *img_path;
int n_rows;
int n_cols;
@ -75,9 +92,8 @@ cltr_photo_grid_navigate(ClutterPhotoGrid *grid,
void /* bleh badly named */
cltr_photo_grid_activate_cell(ClutterPhotoGrid *grid);
void
cltr_photo_grid_populate(ClutterPhotoGrid *grid,
const gchar *imgs_path) ;
gpointer
cltr_photo_grid_populate(gpointer data) ;
void
cltr_photo_grid_redraw(ClutterPhotoGrid *grid);

28
cltr.c
View File

@ -62,6 +62,12 @@ static const GSourceFuncs x_event_funcs = {
NULL
};
void
cltr_dispatch_expose(XExposeEvent *xexpev)
{
cltr_photo_grid_redraw(Grid);
}
void
cltr_dispatch_keypress(XKeyEvent *xkeyev)
{
@ -107,7 +113,8 @@ cltr_dispatch_x_event (XEvent *xevent,
CLTR_DBG("Map Notify Event");
break;
case Expose:
CLTR_DBG("Expose");
CLTR_DBG("Expose"); /* TODO COMPRESS */
cltr_dispatch_expose(&xevent->xexpose);
break;
case KeyPress:
CLTR_DBG("KeyPress");
@ -136,10 +143,8 @@ cltr_init(int *argc, char ***argv)
GSource *source;
CltrXEventSource *display_source;
/* Not just yet ..
g_thread_init (NULL);
XInitThreads ();
*/
// XInitThreads ();
if ((CltrCntx.xdpy = XOpenDisplay(getenv("DISPLAY"))) == NULL)
{
@ -281,15 +286,6 @@ test_idle_cb(gpointer data)
}
gboolean
idle_cb(gpointer data)
{
ClutterPhotoGrid *grid = (ClutterPhotoGrid *)data;
cltr_photo_grid_redraw(grid);
return TRUE;
}
int
main(int argc, char **argv)
@ -312,9 +308,11 @@ main(int argc, char **argv)
Grid = grid; /* laaaaaazy globals */
cltr_photo_grid_redraw(grid);
// cltr_photo_grid_redraw(grid);
g_idle_add(idle_cb, grid);
// g_idle_add(idle_cb, grid);
// g_timeout_add (10, idle_cb, grid);
// g_idle_add(test_idle_cb, (gpointer)win->xwin);

2
cltr.h
View File

@ -29,7 +29,7 @@
GLenum err = glGetError (); /* Roundtrip */ \
if (err != GL_NO_ERROR) \
{ \
g_printerr (__FILE__ ": GL Error: %i [at %s:%d]\n", \
g_printerr (__FILE__ ": GL Error: %x [at %s:%d]\n", \
err, __func__, __LINE__); \
} \
}

View File

@ -538,6 +538,31 @@ pixel_set_vals(PixbufPixel *p,
p->r = r; p->g = g; p->b = b; p->a = a;
}
void
pixbuf_copy(Pixbuf *src_pixb,
Pixbuf *dst_pixb,
int srcx,
int srcy,
int srcw,
int srch,
int dstx,
int dsty)
{
int j, *sp, *dp;
sp = src_pixb->data + (srcy * src_pixb->width) + srcx;
dp = dst_pixb->data + (dsty * dst_pixb->width) + dstx;
while (srch--)
{
j = srcw;
while (j--)
*dp++ = *sp++;
dp += (dst_pixb->width - srcw);
sp += (src_pixb->width - srcw);
}
}
Pixbuf *
pixbuf_scale_down(Pixbuf *pixb,
int new_width,

View File

@ -59,6 +59,16 @@ pixel_set_vals(PixbufPixel *p,
const unsigned char b,
const unsigned char a);
void
pixbuf_copy(Pixbuf *src_pixb,
Pixbuf *dst_pixb,
int srcx,
int srcy,
int srcw,
int srch,
int dstx,
int dsty);
Pixbuf*
pixbuf_scale_down(Pixbuf *pixb,
int new_width,