Software 16 X11 now does rotation.

SVN revision: 31215
This commit is contained in:
Gustavo Sverzut Barbieri 2007-08-07 19:09:53 +00:00
parent b0305ccaa9
commit 4a4a0b0f4c
3 changed files with 326 additions and 73 deletions

View File

@ -1512,15 +1512,75 @@ _ecore_evas_x_move_resize(Ecore_Evas *ee, int x, int y, int w, int h)
}
static void
_ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation)
_ecore_evas_x_rotation_set_internal(Ecore_Evas *ee, int rotation,
Evas_Engine_Info *einfo)
{
int rot_dif;
if (ee->rotation == rotation) return;
if (!strcmp(ee->driver, "gl_x11")) return;
if (!strcmp(ee->driver, "software_16_x11")) return;
rot_dif = ee->rotation - rotation;
if (rot_dif < 0) rot_dif = -rot_dif;
if (rot_dif != 180)
{
int minw, minh, maxw, maxh, basew, baseh, stepw, steph;
evas_engine_info_set(ee->evas, einfo);
if (!ee->prop.fullscreen)
{
ecore_x_window_resize(ee->engine.x.win, ee->h, ee->w);
ee->expecting_resize.w = ee->h;
ee->expecting_resize.h = ee->w;
}
else
{
int w, h;
ecore_x_window_size_get(ee->engine.x.win, &w, &h);
ecore_x_window_resize(ee->engine.x.win, h, w);
if ((rotation == 0) || (rotation == 180))
{
evas_output_size_set(ee->evas, ee->w, ee->h);
evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
}
else
{
evas_output_size_set(ee->evas, ee->h, ee->w);
evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
}
if (ee->func.fn_resize) ee->func.fn_resize(ee);
}
ecore_evas_size_min_get(ee, &minw, &minh);
ecore_evas_size_max_get(ee, &maxw, &maxh);
ecore_evas_size_base_get(ee, &basew, &baseh);
ecore_evas_size_step_get(ee, &stepw, &steph);
ee->rotation = rotation;
ecore_evas_size_min_set(ee, minh, minw);
ecore_evas_size_max_set(ee, maxh, maxw);
ecore_evas_size_base_set(ee, baseh, basew);
ecore_evas_size_step_set(ee, steph, stepw);
_ecore_evas_x_mouse_move_process(ee, ee->mouse.x, ee->mouse.y,
ecore_x_current_time_get());
}
else
{
evas_engine_info_set(ee->evas, einfo);
ee->rotation = rotation;
_ecore_evas_x_mouse_move_process(ee, ee->mouse.x, ee->mouse.y,
ecore_x_current_time_get());
if (ee->func.fn_resize) ee->func.fn_resize(ee);
}
if ((ee->rotation == 90) || (ee->rotation == 270))
evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
else
evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
}
static void
_ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation)
{
if (ee->rotation == rotation) return;
if (!strcmp(ee->driver, "gl_x11")) return;
if (!strcmp(ee->driver, "software_x11"))
{
#ifdef BUILD_ECORE_X
@ -1534,63 +1594,23 @@ _ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation)
einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
#endif /* HAVE_ECORE_X_XCB */
if (!einfo) return;
if (rot_dif != 180)
{
int minw, minh, maxw, maxh, basew, baseh, stepw, steph;
einfo->info.rotation = rotation;
evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
if (!ee->prop.fullscreen)
{
ecore_x_window_resize(ee->engine.x.win, ee->h, ee->w);
ee->expecting_resize.w = ee->h;
ee->expecting_resize.h = ee->w;
}
else
{
int w, h;
ecore_x_window_size_get(ee->engine.x.win, &w, &h);
ecore_x_window_resize(ee->engine.x.win, h, w);
if ((rotation == 0) || (rotation == 180))
{
evas_output_size_set(ee->evas, ee->w, ee->h);
evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
}
else
{
evas_output_size_set(ee->evas, ee->h, ee->w);
evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
}
if (ee->func.fn_resize) ee->func.fn_resize(ee);
}
ecore_evas_size_min_get(ee, &minw, &minh);
ecore_evas_size_max_get(ee, &maxw, &maxh);
ecore_evas_size_base_get(ee, &basew, &baseh);
ecore_evas_size_step_get(ee, &stepw, &steph);
ee->rotation = rotation;
ecore_evas_size_min_set(ee, minh, minw);
ecore_evas_size_max_set(ee, maxh, maxw);
ecore_evas_size_base_set(ee, baseh, basew);
ecore_evas_size_step_set(ee, steph, stepw);
_ecore_evas_x_mouse_move_process(ee, ee->mouse.x, ee->mouse.y,
ecore_x_current_time_get());
}
else
{
einfo->info.rotation = rotation;
evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
ee->rotation = rotation;
_ecore_evas_x_mouse_move_process(ee, ee->mouse.x, ee->mouse.y,
ecore_x_current_time_get());
if (ee->func.fn_resize) ee->func.fn_resize(ee);
}
if ((ee->rotation == 90) || (ee->rotation == 270))
evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
else
evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
einfo->info.rotation = rotation;
_ecore_evas_x_rotation_set_internal
(ee, rotation, (Evas_Engine_Info *)einfo);
#endif /* BUILD_ECORE_X */
}
else if (!strcmp(ee->driver, "software_16_x11"))
{
#if defined(BUILD_ECORE_X) && defined(BUILD_ECORE_EVAS_X11_16)
Evas_Engine_Info_Software_16_X11 *einfo;
einfo = (Evas_Engine_Info_Software_16_X11 *)evas_engine_info_get(ee->evas);
if (!einfo) return;
einfo->info.rotation = rotation;
_ecore_evas_x_rotation_set_internal
(ee, rotation, (Evas_Engine_Info *)einfo);
#endif /* defined(BUILD_ECORE_X) && defined(BUILD_ECORE_EVAS_X11_16) */
}
}
static void

View File

@ -15,6 +15,7 @@ struct _Evas_Engine_Info_Software_16_X11
struct {
Display *display;
Drawable drawable;
int rotation;
} info;
};
#endif

View File

@ -15,11 +15,12 @@ struct _Render_Engine
Display *disp;
Drawable draw;
GC gc;
int w, h;
int w, h, rot;
Tilebuf *tb;
Tilebuf_Rect *rects;
Tilebuf_Rect *cur_rect;
X_Output_Buffer *shbuf;
Soft16_Image *tmp_out; /* used by indirect render, like rotation */
Region clip_rects;
unsigned char end : 1;
unsigned char shm : 1;
@ -63,6 +64,52 @@ eng_info_free(Evas *e, void *info)
free(in);
}
static void
_tmp_out_free(Soft16_Image *tmp_out)
{
free(tmp_out->pixels);
free(tmp_out);
}
static void
_tmp_out_alloc(Render_Engine *re)
{
Tilebuf_Rect *r;
int w = 0, h = 0;
for (r = re->rects; r; r = (Tilebuf_Rect *)(r->_list_data.next))
{
if (r->w > w) w = r->w;
if (r->h > h) h = r->h;
}
if (re->tmp_out)
{
if ((re->tmp_out->w < w) || (re->tmp_out->h < h))
{
_tmp_out_free(re->tmp_out);
re->tmp_out = NULL;
}
}
if (!re->tmp_out)
{
Soft16_Image *im;
im = calloc(1, sizeof(Soft16_Image));
im->w = w;
im->h = h;
im->stride = w + ((w % 4) ? (4 - (w % 4)) : 0);
im->have_alpha = 0;
im->references = 1;
im->free_pixels = 1;
im->pixels = malloc(h * im->stride * sizeof(DATA16));
re->tmp_out = im;
}
}
static void
eng_setup(Evas *e, void *in)
{
@ -106,6 +153,7 @@ eng_setup(Evas *e, void *in)
re->gc = XCreateGC(re->disp, re->draw, 0, &gcv);
re->w = e->output.w;
re->h = e->output.h;
re->rot = info->info.rotation;
re->tb = evas_common_tilebuf_new(e->output.w, e->output.h);
if (re->tb)
evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
@ -125,9 +173,15 @@ eng_setup(Evas *e, void *in)
re->gc = XCreateGC(re->disp, re->draw, 0, &gcv);
re->w = e->output.w;
re->h = e->output.h;
re->rot = info->info.rotation;
re->tb = evas_common_tilebuf_new(e->output.w, e->output.h);
if (re->tb)
evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
if (re->tmp_out)
{
_tmp_out_free(re->tmp_out);
re->tmp_out = NULL;
}
}
if (!e->engine.data.output) return;
/* add a draw context if we dont have one */
@ -149,6 +203,7 @@ eng_output_free(void *data)
if (re->gc) XFreeGC(re->disp, re->gc);
if (re->tb) evas_common_tilebuf_free(re->tb);
if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
if (re->tmp_out) _tmp_out_free(re->tmp_out);
free(re);
evas_common_font_shutdown();
@ -180,6 +235,11 @@ eng_output_resize(void *data, int w, int h)
XDestroyRegion(re->clip_rects);
re->clip_rects = NULL;
}
if (re->tmp_out)
{
_tmp_out_free(re->tmp_out);
re->tmp_out = NULL;
}
}
static void
@ -218,6 +278,29 @@ eng_output_redraws_clear(void *data)
evas_common_tilebuf_clear(re->tb);
}
static inline void
_output_buffer_alloc(Render_Engine *re)
{
int w, h;
if (re->shbuf) return;
if ((re->rot == 0) || (re->rot == 180))
{
w = re->w;
h = re->h;
}
else
{
w = re->h;
h = re->w;
}
re->shbuf = evas_software_x11_x_output_buffer_new
(re->disp, DefaultVisual(re->disp, DefaultScreen(re->disp)),
DefaultDepth(re->disp, DefaultScreen(re->disp)),
w, h, 1, NULL);
}
static void *
eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch)
{
@ -237,11 +320,8 @@ eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, i
if (!re->rects) return NULL;
re->cur_rect = re->rects;
if (!re->shbuf)
re->shbuf = evas_software_x11_x_output_buffer_new
(re->disp, DefaultVisual(re->disp, DefaultScreen(re->disp)),
DefaultDepth(re->disp, DefaultScreen(re->disp)),
re->w, re->h, 1, NULL);
_output_buffer_alloc(re);
if (re->rot != 0) _tmp_out_alloc(re); /* grows if required */
}
if (!re->cur_rect)
{
@ -259,9 +339,128 @@ eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, i
re->end = 1;
}
*cx = ux; *cy = uy; *cw = uw; *ch = uh;
*x = ux; *y = uy; *w = uw; *h = uh;
return &re->shbuf->im;
if (re->rot == 0)
{
*cx = ux; *cy = uy; *cw = uw; *ch = uh;
return &re->shbuf->im;
}
else
{
*cx = 0; *cy = 0; *cw = uw; *ch = uh;
return re->tmp_out;
}
}
static void
_blit_rot_90(Soft16_Image *dst, const Soft16_Image *src,
int out_x, int out_y, int w, int h)
{
DATA16 *dp, *sp;
int x, y;
sp = src->pixels;
dp = dst->pixels + (out_x +
(w + out_y - 1) * dst->stride);
for (y = 0; y < h; y++)
{
DATA16 *dp_itr, *sp_itr;
sp_itr = sp;
dp_itr = dp;
for (x = 0; x < w; x++)
{
*dp_itr = *sp_itr;
sp_itr++;
dp_itr -= dst->stride;
}
sp += src->stride;
dp++;
}
}
static void
_blit_rot_180(Soft16_Image *dst, const Soft16_Image *src,
int out_x, int out_y, int w, int h)
{
DATA16 *dp, *sp;
int x, y;
sp = src->pixels;
dp = dst->pixels + ((w + out_x - 1) +
(h + out_y - 1) * dst->stride);
for (y = 0; y < h; y++)
{
DATA16 *dp_itr, *sp_itr;
sp_itr = sp;
dp_itr = dp;
for (x = 0; x < w; x++)
{
*dp_itr = *sp_itr;
sp_itr++;
dp_itr--;
}
sp += src->stride;
dp -= dst->stride;
}
}
static void
_blit_rot_270(Soft16_Image *dst, const Soft16_Image *src,
int out_x, int out_y, int w, int h)
{
DATA16 *dp, *sp;
int x, y;
sp = src->pixels;
dp = dst->pixels + ((h + out_x - 1) +
out_y * dst->stride);
for (y = 0; y < h; y++)
{
DATA16 *dp_itr, *sp_itr;
sp_itr = sp;
dp_itr = dp;
for (x = 0; x < w; x++)
{
*dp_itr = *sp_itr;
sp_itr++;
dp_itr += dst->stride;
}
sp += src->stride;
dp--;
}
}
static void
_tmp_out_process(Render_Engine *re, int out_x, int out_y, int w, int h)
{
Soft16_Image *d, *s;
DATA16 *dp, *sp;
int y, x, d_dir;
d = &re->shbuf->im;
s = re->tmp_out;
if ((w < 1) || (h < 1) || (out_x >= d->w) || (out_y >= d->h))
return;
if (re->rot == 90)
_blit_rot_90(d, s, out_x, out_y, w, h);
else if (re->rot == 180)
_blit_rot_180(d, s, out_x, out_y, w, h);
else if (re->rot == 270)
_blit_rot_270(d, s, out_x, out_y, w, h);
}
static void
@ -275,10 +474,37 @@ eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int
if (!re->clip_rects)
re->clip_rects = XCreateRegion();
r.x = x;
r.y = y;
r.width = w;
r.height = h;
if (re->rot == 0)
{
r.x = x;
r.y = y;
r.width = w;
r.height = h;
}
else if (re->rot == 90)
{
r.x = y;
r.y = re->w - w - x;
r.width = h;
r.height = w;
}
else if (re->rot == 180)
{
r.x = re->w - w - x;
r.y = re->h - h - y;
r.width = w;
r.height = h;
}
else if (re->rot == 270)
{
r.x = re->h - h - y;
r.y = x;
r.width = h;
r.height = w;
}
if (re->rot != 0)
_tmp_out_process(re, r.x, r.y, w, h);
XUnionRectWithRegion(&r, re->clip_rects, re->clip_rects);
}
@ -286,6 +512,7 @@ static void
eng_output_flush(void *data)
{
Render_Engine *re;
int w, h;
re = (Render_Engine *)data;
if (re->clip_rects)
@ -296,8 +523,8 @@ eng_output_flush(void *data)
}
else return;
evas_software_x11_x_output_buffer_paste(re->shbuf, re->draw, re->gc,
0, 0, re->w, re->h, 0);
evas_software_x11_x_output_buffer_paste
(re->shbuf, re->draw, re->gc, 0, 0, re->shbuf->im.w, re->shbuf->im.h, 0);
XSetClipMask(re->disp, re->gc, None);
}
@ -317,6 +544,11 @@ eng_output_idle_flush(void *data)
XDestroyRegion(re->clip_rects);
re->clip_rects = NULL;
}
if (re->tmp_out)
{
_tmp_out_free(re->tmp_out);
re->tmp_out = NULL;
}
}