EAPI int evas_common_tilebuf_add_redraw(Tilebuf *tb, int x, int y, int w, int h) { #ifdef RECTUPDATE int i; if ((w <= 0) || (h <= 0)) return 0; RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h); if ((w <= 0) || (h <= 0)) return 0; for (i = 0; i < h; i++) evas_common_regionbuf_span_add(tb->rb, x, x + w - 1, y + i); return 1; #elif defined(EVAS_RECT_SPLIT) return _add_redraw(&tb->rects, tb->outbuf_w, tb->outbuf_h, x, y, w, h); #else int tx1, tx2, ty1, ty2, tfx1, tfx2, tfy1, tfy2, xx, yy; int num; if ((w <= 0) || (h <= 0)) return 0; RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h); if ((w <= 0) || (h <= 0)) return 0; num = 0; /* wipes out any motion vectors in tiles it touches into redraws */ if (tilebuf_x_intersect(tb, x, w, &tx1, &tx2, &tfx1, &tfx2) && tilebuf_y_intersect(tb, y, h, &ty1, &ty2, &tfy1, &tfy2)) { Tilebuf_Tile *tbt; int delta_x; int delta_y; tbt = &(TILE(tb, tx1, ty1)); delta_x = tx2 - tx1 + 1; delta_y = ty2 - ty1 + 1; for (yy = delta_y; yy > 0; yy--) { Tilebuf_Tile *tbti; tbti = tbt; for (xx = delta_x; xx > 0; xx--) { tbti->redraw = 1; tbti++; } tbt += tb->tiles.w; } num = (tx2 - tx1 + 1) * (ty2 - ty1 + 1); } return num; #endif }
static inline int _add_redraw(list_t *rects, int max_w, int max_h, int x, int y, int w, int h) { rect_node_t *rn; if ((w <= 0) || (h <= 0)) return 0; RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, max_w, max_h); if ((w <= 0) || (h <= 0)) return 0; x >>= 1; y >>= 1; w += 2; w >>= 1; h += 2; h >>= 1; rn = (rect_node_t *)rect_list_node_pool_get(); rn->_lst = list_node_zeroed; rect_init(&rn->rect, x, y, w, h); //INF("ACCOUNTING: add_redraw: %4d,%4d %3dx%3d", x, y, w, h); //testing on my core2 duo desktop - fuzz of 32 or 48 is best. #define FUZZ 32 rect_list_add_split_fuzzy_and_merge(rects, (list_node_t *)rn, FUZZ * FUZZ, FUZZ * FUZZ); return 1; }
EAPI void evas_common_draw_context_clip_clip(RGBA_Draw_Context *dc, int x, int y, int w, int h) { if (dc->clip.use) { RECTS_CLIP_TO_RECT(dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h, x, y, w, h); } else evas_common_draw_context_set_clip(dc, x, y, w, h); }
RGBA_Image * evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch) { RGBA_Image *img = NULL; if ((w <= 0) || (h <= 0)) return NULL; /* DBG("Outbuf Region New: %d %d %d %d", x, y, w, h); */ RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, ob->w, ob->h); if ((ob->rotation == 0) && (ob->depth == 32)) { Eina_Rectangle *rect; if (!(rect = eina_rectangle_new(x, y, w, h))) return NULL; #ifdef EVAS_CSERVE2 if (evas_cserve2_use_get()) img = (RGBA_Image *)evas_cache2_image_empty(evas_common_image_cache2_get()); else #endif img = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get()); if (!img) { eina_rectangle_free(rect); return NULL; } img->cache_entry.flags.alpha = ob->destination_alpha; #ifdef EVAS_CSERVE2 if (evas_cserve2_use_get()) evas_cache2_image_surface_alloc(&img->cache_entry, w, h); else #endif evas_cache_image_surface_alloc(&img->cache_entry, w, h); img->extended_info = rect; if (cx) *cx = 0; if (cy) *cy = 0; if (cw) *cw = w; if (ch) *ch = h; /* add this cached image data to pending writes */ ob->priv.pending_writes = eina_list_append(ob->priv.pending_writes, img); } return img; }
static void _soft8_rectangle_draw_int(Soft8_Image * dst, RGBA_Draw_Context * dc, Eina_Rectangle dr) { int dst_offset; if (_is_empty_rectangle(&dr)) return; RECTS_CLIP_TO_RECT(dr.x, dr.y, dr.w, dr.h, 0, 0, dst->cache_entry.w, dst->cache_entry.h); if (_is_empty_rectangle(&dr)) return; if (dc->clip.use) RECTS_CLIP_TO_RECT(dr.x, dr.y, dr.w, dr.h, dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h); if (_is_empty_rectangle(&dr)) return; if (A_VAL(&dc->col.col) == 0) return; dst_offset = dr.x + (dr.y * dst->stride); if (!dst->cache_entry.flags.alpha) { DATA8 gry8; DATA8 alpha; alpha = A_VAL(&dc->col.col); gry8 = GRY_8_FROM_RGB(&dc->col.col); if (alpha == 0xff) _soft8_rectangle_draw_solid_solid(dst, dst_offset, dr.w, dr.h, gry8); else if (alpha > 0) _soft8_rectangle_draw_transp_solid (dst, dst_offset, dr.w, dr.h, gry8, alpha); } else ERR("Unsupported feature: drawing rectangle to non-opaque destination."); }
EAPI void evas_common_draw_context_add_cutout(RGBA_Draw_Context *dc, int x, int y, int w, int h) { // if (dc->cutout.rects > 512) return; if (dc->clip.use) { #if 1 // this is a bit faster int xa1, xa2, xb1, xb2; xa1 = x; xa2 = xa1 + w - 1; xb1 = dc->clip.x; if (xa2 < xb1) return; xb2 = xb1 + dc->clip.w - 1; if (xa1 >= xb2) return; if (xa2 > xb2) xa2 = xb2; if (xb1 > xa1) xa1 = xb1; x = xa1; w = xa2 - xa1 + 1; xa1 = y; xa2 = xa1 + h - 1; xb1 = dc->clip.y; if (xa2 < xb1) return; xb2 = xb1 + dc->clip.h - 1; if (xa1 >= xb2) return; if (xa2 > xb2) xa2 = xb2; if (xb1 > xa1) xa1 = xb1; y = xa1; h = xa2 - xa1 + 1; #else RECTS_CLIP_TO_RECT(x, y, w, h, dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h); #endif if ((w < 1) || (h < 1)) return; } evas_common_draw_context_cutouts_add(&dc->cutout, x, y, w, h); }
static void rectangle_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h) { RGBA_Gfx_Func func; int yy; DATA32 *ptr; RECTS_CLIP_TO_RECT(x, y, w, h, dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h); if ((w <= 0) || (h <= 0)) return; func = evas_common_gfx_func_composite_color_span_get(dc->col.col, dst, w, dc->render_op); ptr = dst->image.data + (y * dst->cache_entry.w) + x; for (yy = 0; yy < h; yy++) { #ifdef EVAS_SLI if (((yy + y) % dc->sli.h) == dc->sli.y) #endif { func(NULL, NULL, dc->col.col, ptr, w); } ptr += dst->cache_entry.w; } }
static void rectangle_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h) { RGBA_Gfx_Func func; int yy; DATA32 *ptr; RECTS_CLIP_TO_RECT(x, y, w, h, dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h); if ((w <= 0) || (h <= 0)) return; #ifdef HAVE_PIXMAN # ifdef PIXMAN_RECT pixman_op_t op = PIXMAN_OP_SRC; // _EVAS_RENDER_COPY if (dc->render_op == _EVAS_RENDER_BLEND) op = PIXMAN_OP_OVER; if ((dst->pixman.im) && (dc->col.pixman_color_image)) { pixman_image_composite(op, dc->col.pixman_color_image, NULL, dst->pixman.im, x, y, 0, 0, x, y, w, h); } else # endif #endif { func = evas_common_gfx_func_composite_color_span_get(dc->col.col, dst, w, dc->render_op); ptr = dst->image.data + (y * dst->cache_entry.w) + x; for (yy = 0; yy < h; yy++) { func(NULL, NULL, dc->col.col, ptr, w); ptr += dst->cache_entry.w; } } }
void evas_common_soft8_polygon_draw(Soft8_Image * dst, RGBA_Draw_Context * dc, RGBA_Polygon_Point * points, int x, int y) { RGBA_Polygon_Point *pt; RGBA_Vertex *point; RGBA_Edge *edges; int num_active_edges; int n; int i, j, k; int y0, y1, yi; int ext_x, ext_y, ext_w, ext_h; int *sorted_index; DATA8 alpha; DATA8 gry8; alpha = A_VAL(&dc->col.col); if (alpha == 0) return; alpha++; gry8 = GRY_8_FROM_RGB(&dc->col.col); ext_x = 0; ext_y = 0; ext_w = dst->cache_entry.w; ext_h = dst->cache_entry.h; if (dc->clip.use) RECTS_CLIP_TO_RECT(ext_x, ext_y, ext_w, ext_h, dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h); if ((ext_w <= 0) || (ext_h <= 0)) return; n = 0; EINA_INLIST_FOREACH(points, pt) n++; if (n < 3) return; edges = malloc(sizeof(RGBA_Edge) * n); if (!edges) return; point = malloc(sizeof(RGBA_Vertex) * n); if (!point) { free(edges); return; } sorted_index = malloc(sizeof(int) * n); if (!sorted_index) { free(edges); free(point); return; } k = 0; EINA_INLIST_FOREACH(points, pt) { point[k].x = pt->x + x; point[k].y = pt->y + y; point[k].i = k; k++; }
static void scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h) { int x, y; int *lin_ptr; DATA32 *buf, *dptr; DATA32 **row_ptr; DATA32 *ptr, *dst_ptr, *src_data, *dst_data; int dst_clip_x, dst_clip_y, dst_clip_w, dst_clip_h; int m_clip_x = 0, m_clip_y = 0, m_clip_w = 0, m_clip_h = 0, mdx = 0, mdy = 0; int src_w, src_h, dst_w, dst_h; RGBA_Gfx_Func func; RGBA_Image *maskobj = NULL; DATA8 *mask = NULL; if (!(RECTS_INTERSECT(dst_region_x, dst_region_y, dst_region_w, dst_region_h, 0, 0, dst->cache_entry.w, dst->cache_entry.h))) return; if (!(RECTS_INTERSECT(src_region_x, src_region_y, src_region_w, src_region_h, 0, 0, src->cache_entry.w, src->cache_entry.h))) return; src_w = src->cache_entry.w; src_h = src->cache_entry.h; dst_w = dst->cache_entry.w; dst_h = dst->cache_entry.h; src_data = src->image.data; dst_data = dst->image.data; if (dc->clip.use) { dst_clip_x = dc->clip.x; dst_clip_y = dc->clip.y; dst_clip_w = dc->clip.w; dst_clip_h = dc->clip.h; if (dst_clip_x < 0) { dst_clip_w += dst_clip_x; dst_clip_x = 0; } if (dst_clip_y < 0) { dst_clip_h += dst_clip_y; dst_clip_y = 0; } if ((dst_clip_x + dst_clip_w) > dst_w) dst_clip_w = dst_w - dst_clip_x; if ((dst_clip_y + dst_clip_h) > dst_h) dst_clip_h = dst_h - dst_clip_y; } else { dst_clip_x = 0; dst_clip_y = 0; dst_clip_w = dst_w; dst_clip_h = dst_h; } if (dc->mask.mask) { m_clip_x = dc->mask.x; m_clip_y = dc->mask.y; m_clip_w = dc->mask.mask->cache_entry.w; m_clip_h = dc->mask.mask->cache_entry.h; RECTS_CLIP_TO_RECT(m_clip_x, m_clip_y, m_clip_w, m_clip_h, dst_clip_x, dst_clip_y, dst_clip_w, dst_clip_h); if ((m_clip_w <= 0) || (m_clip_h <= 0)) return; dst_clip_x = m_clip_x; dst_clip_y = m_clip_y; dst_clip_w = m_clip_w; dst_clip_h = m_clip_h; } if (dst_clip_x < dst_region_x) { dst_clip_w += dst_clip_x - dst_region_x; dst_clip_x = dst_region_x; } if ((dst_clip_x + dst_clip_w) > (dst_region_x + dst_region_w)) dst_clip_w = dst_region_x + dst_region_w - dst_clip_x; if (dst_clip_y < dst_region_y) { dst_clip_h += dst_clip_y - dst_region_y; dst_clip_y = dst_region_y; } if ((dst_clip_y + dst_clip_h) > (dst_region_y + dst_region_h)) dst_clip_h = dst_region_y + dst_region_h - dst_clip_y; if ((src_region_w <= 0) || (src_region_h <= 0) || (dst_region_w <= 0) || (dst_region_h <= 0) || (dst_clip_w <= 0) || (dst_clip_h <= 0)) return; /* sanitise x */ if (src_region_x < 0) { dst_region_x -= (src_region_x * dst_region_w) / src_region_w; dst_region_w += (src_region_x * dst_region_w) / src_region_w; src_region_w += src_region_x; src_region_x = 0; } if (src_region_x >= src_w) return; if ((src_region_x + src_region_w) > src_w) { dst_region_w = (dst_region_w * (src_w - src_region_x)) / (src_region_w); src_region_w = src_w - src_region_x; } if (dst_region_w <= 0) return; if (src_region_w <= 0) return; if (dst_clip_x < 0) { dst_clip_w += dst_clip_x; dst_clip_x = 0; } if (dst_clip_w <= 0) return; if (dst_clip_x >= dst_w) return; if (dst_clip_x < dst_region_x) { dst_clip_w += (dst_clip_x - dst_region_x); dst_clip_x = dst_region_x; } if ((dst_clip_x + dst_clip_w) > dst_w) { dst_clip_w = dst_w - dst_clip_x; } if (dst_clip_w <= 0) return; /* sanitise y */ if (src_region_y < 0) { dst_region_y -= (src_region_y * dst_region_h) / src_region_h; dst_region_h += (src_region_y * dst_region_h) / src_region_h; src_region_h += src_region_y; src_region_y = 0; } if (src_region_y >= src_h) return; if ((src_region_y + src_region_h) > src_h) { dst_region_h = (dst_region_h * (src_h - src_region_y)) / (src_region_h); src_region_h = src_h - src_region_y; } if (dst_region_h <= 0) return; if (src_region_h <= 0) return; if (dst_clip_y < 0) { dst_clip_h += dst_clip_y; dst_clip_y = 0; } if (dst_clip_h <= 0) return; if (dst_clip_y >= dst_h) return; if (dst_clip_y < dst_region_y) { dst_clip_h += (dst_clip_y - dst_region_y); dst_clip_y = dst_region_y; } if ((dst_clip_y + dst_clip_h) > dst_h) { dst_clip_h = dst_h - dst_clip_y; } if (dst_clip_h <= 0) return; /* allocate scale lookup tables */ lin_ptr = alloca(dst_clip_w * sizeof(int)); row_ptr = alloca(dst_clip_h * sizeof(DATA32 *)); /* figure out dst jump */ //dst_jump = dst_w - dst_clip_w; /* figure out dest start ptr */ dst_ptr = dst_data + dst_clip_x + (dst_clip_y * dst_w); if (dc->mask.mask) { func = evas_common_gfx_func_composite_pixel_mask_span_get(src, dst, dst_clip_w, dc->render_op); maskobj = dc->mask.mask; mask = maskobj->mask.mask; /* if (1 || dst_region_w > src_region_w || dst_region_h > src_region_h){ printf("Mask w/h: %d/%d\n",maskobj->cache_entry.w, maskobj->cache_entry.h); printf("Warning: Unscaled mask (%d/%d) // (%d/%d)\n", dst_region_w,src_region_w, dst_region_h,src_region_h); } */ } else if (dc->mul.use) func = evas_common_gfx_func_composite_pixel_color_span_get(src, dc->mul.col, dst, dst_clip_w, dc->render_op); else func = evas_common_gfx_func_composite_pixel_span_get(src, dst, dst_clip_w, dc->render_op); if ((dst_region_w == src_region_w) && (dst_region_h == src_region_h)) { #ifdef HAVE_PIXMAN # ifdef PIXMAN_IMAGE_SCALE_SAMPLE if ((src->pixman.im) && (dst->pixman.im) && (!dc->mask.mask) && ((!dc->mul.use) || ((dc->mul.use) && (dc->mul.col == 0xffffffff))) && ((dc->render_op == _EVAS_RENDER_COPY) || (dc->render_op == _EVAS_RENDER_BLEND))) { pixman_op_t op = PIXMAN_OP_SRC; // _EVAS_RENDER_COPY if (dc->render_op == _EVAS_RENDER_BLEND) op = PIXMAN_OP_OVER; pixman_image_composite(op, src->pixman.im, NULL, dst->pixman.im, (dst_clip_x - dst_region_x) + src_region_x, (dst_clip_y - dst_region_y) + src_region_y, 0, 0, dst_clip_x, dst_clip_y, dst_clip_w, dst_clip_h); } else if ((src->pixman.im) && (dst->pixman.im) && (dc->mask.mask) && (dc->mask.mask->pixman.im) && ((dc->render_op == _EVAS_RENDER_COPY) || (dc->render_op == _EVAS_RENDER_BLEND))) { // In case of pixel and color operation. pixman_op_t op = PIXMAN_OP_SRC; // _EVAS_RENDER_COPY if (dc->render_op == _EVAS_RENDER_BLEND) op = PIXMAN_OP_OVER; pixman_image_composite(op, src->pixman.im, dc->mask.mask->pixman.im, dst->pixman.im, (dst_clip_x - dst_region_x) + src_region_x, (dst_clip_y - dst_region_y) + src_region_y, 0, 0, dst_clip_x, dst_clip_y, dst_clip_w, dst_clip_h); } else # endif #endif { ptr = src_data + ((dst_clip_y - dst_region_y + src_region_y) * src_w) + (dst_clip_x - dst_region_x) + src_region_x; if (mask) { mdx = (m_clip_x - dc->mask.x) + (m_clip_x - dst_clip_x); mdy = (m_clip_y - dc->mask.y) + (m_clip_y - dst_clip_y); mask += mdx + (mdy * maskobj->cache_entry.w); } for (y = 0; y < dst_clip_h; y++) { /* * blend here [clip_w *] ptr -> dst_ptr * */ func(ptr, mask, dc->mul.col, dst_ptr, dst_clip_w); ptr += src_w; dst_ptr += dst_w; if (mask) mask += maskobj->cache_entry.w; } } } else { /* fill scale tables */ for (x = 0; x < dst_clip_w; x++) lin_ptr[x] = (((x + dst_clip_x - dst_region_x) * src_region_w) / dst_region_w) + src_region_x; for (y = 0; y < dst_clip_h; y++) row_ptr[y] = src_data + (((((y + dst_clip_y - dst_region_y) * src_region_h) / dst_region_h) + src_region_y) * src_w); /* scale to dst */ dptr = dst_ptr; #ifdef DIRECT_SCALE if ((!src->cache_entry.flags.alpha) && (!dst->cache_entry.flags.alpha) && (!dc->mul.use)) { for (y = 0; y < dst_clip_h; y++) { dst_ptr = dptr; for (x = 0; x < dst_clip_w; x++) { ptr = row_ptr[y] + lin_ptr[x]; *dst_ptr = *ptr; dst_ptr++; } dptr += dst_w; } } else #endif { /* a scanline buffer */ buf = alloca(dst_clip_w * sizeof(DATA32)); for (y = 0; y < dst_clip_h; y++) { dst_ptr = buf; for (x = 0; x < dst_clip_w; x++) { ptr = row_ptr[y] + lin_ptr[x]; *dst_ptr = *ptr; dst_ptr++; } /* * blend here [clip_w *] buf -> dptr * */ func(buf, NULL, dc->mul.col, dptr, dst_clip_w); dptr += dst_w; } } } }
void evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h) { Gfx_Func_Convert func = NULL; Eina_Rectangle rect = {0, 0, 0, 0}, pr; DATA32 *src; DATA8 *dst; Buffer *buff; int bpp = 0, bpl = 0; int rx = 0, ry = 0; /* check for valid output buffer */ if (!ob) return; /* check for pending writes */ if (!ob->priv.pending_writes) return; /* check for valid source data */ if (!(src = update->image.data)) return; /* check for valid desination data */ buff = &(ob->priv.buffer[ob->priv.curr]); if (!(dst = buff->data)) return; if ((ob->rotation == 0) || (ob->rotation == 180)) { func = evas_common_convert_func_get(0, w, h, ob->depth, RED_MASK, GREEN_MASK, BLUE_MASK, PAL_MODE_NONE, ob->rotation); } else if ((ob->rotation == 90) || (ob->rotation == 270)) { func = evas_common_convert_func_get(0, h, w, ob->depth, RED_MASK, GREEN_MASK, BLUE_MASK, PAL_MODE_NONE, ob->rotation); } /* make sure we have a valid convert function */ if (!func) return; /* based on rotation, set rectangle position */ if (ob->rotation == 0) { rect.x = x; rect.y = y; } else if (ob->rotation == 90) { rect.x = y; rect.y = (ob->w - x - w); } else if (ob->rotation == 180) { rect.x = (ob->w - x - w); rect.y = (ob->h - y - h); } else if (ob->rotation == 270) { rect.x = (ob->h - y - h); rect.y = x; } /* based on rotation, set rectangle size */ if ((ob->rotation == 0) || (ob->rotation == 180)) { rect.w = w; rect.h = h; } else if ((ob->rotation == 90) || (ob->rotation == 270)) { rect.w = h; rect.h = w; } bpp = (ob->depth / 8); if (bpp <= 0) return; bpl = buff->stride; if (ob->rotation == 0) { RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, buff->w, buff->h); dst += (bpl * rect.y) + (rect.x * bpp); w -= rx; } else if (ob->rotation == 180) { pr = rect; RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, buff->w, buff->h); rx = pr.w - rect.w; ry = pr.h - rect.h; src += (update->cache_entry.w * ry) + rx; w -= rx; } else if (ob->rotation == 90) { pr = rect; RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, buff->w, buff->h); rx = pr.w - rect.w; ry = pr.h - rect.h; src += ry; w -= ry; } else if (ob->rotation == 270) { pr = rect; RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, buff->w, buff->h); rx = pr.w - rect.w; ry = pr.h - rect.h; src += (update->cache_entry.w * rx); w -= ry; } if ((rect.w <= 0) || (rect.h <= 0)) return; func(src, dst, (update->cache_entry.w - w), ((bpl / bpp) - rect.w), rect.w, rect.h, x + rx, y + ry, NULL); }
EAPI int evas_common_tilebuf_del_redraw(Tilebuf *tb, int x, int y, int w, int h) { #ifdef RECTUPDATE int i; for (i = 0; i < h; i++) evas_common_regionbuf_span_del(tb->rb, x, x + w - 1, y + i); #elif defined(EVAS_RECT_SPLIT) rect_t r; if (!tb->rects.head) return 0; if ((w <= 0) || (h <= 0)) return 0; RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h); if ((w <= 0) || (h <= 0)) return 0; x += 1; y += 1; x >>= 1; y >>= 1; w -= 1; w >>= 1; h -= 1; h >>= 1; if ((w <= 0) || (h <= 0)) return 0; rect_init(&r, x, y, w, h); //ERR("ACCOUNTING: del_redraw: %4d,%4d %3dx%3d", x, y, w, h); rect_list_del_split_strict(&tb->rects, r); tb->need_merge = 1; return 0; #else int tx1, tx2, ty1, ty2, tfx1, tfx2, tfy1, tfy2, xx, yy; int num; num = 0; /* wipes out any motion vectors in tiles it touches into redraws */ if (tilebuf_x_intersect(tb, x, w, &tx1, &tx2, &tfx1, &tfx2) && tilebuf_y_intersect(tb, y, h, &ty1, &ty2, &tfy1, &tfy2)) { Tilebuf_Tile *tbt; int delta_y; int delta_x; if (!tfx1) tx1++; if (!tfx2) tx2--; if (!tfy1) ty1++; if (!tfy2) ty2--; tbt = &(TILE(tb, tx1, ty1)); delta_x = tx2 - tx1 + 1; delta_y = ty2 - ty1 + 1; for (yy = delta_y; yy > 0; yy--) { Tilebuf_Tile *tbti; tbti = tbt; for (xx = delta_x; xx > 0; xx--) { tbti->redraw = 0; tbti++; } tbt += tb->tiles.w; } num = (tx2 - tx1 + 1) * (ty2 - ty1 + 1); } return num; #endif }
EAPI Tilebuf_Rect * evas_common_tilebuf_get_render_rects(Tilebuf *tb) { #ifdef RECTUPDATE return evas_common_regionbuf_rects_get(tb->rb); #elif defined(EVAS_RECT_SPLIT) list_node_t *n; Tilebuf_Rect *rects = NULL; if (tb->need_merge) { list_t to_merge; to_merge = tb->rects; tb->rects = list_zeroed; rect_list_merge_rects(&tb->rects, &to_merge, FUZZ * FUZZ); tb->need_merge = 0; } for (n = tb->rects.head; n; n = n->next) { rect_t cur; cur = ((rect_node_t *)n)->rect; cur.left <<= 1; cur.top <<= 1; cur.width <<= 1; cur.height <<= 1; RECTS_CLIP_TO_RECT(cur.left, cur.top, cur.width, cur.height, 0, 0, tb->outbuf_w, tb->outbuf_h); if ((cur.width > 0) && (cur.height > 0)) { Tilebuf_Rect *r; r = malloc(sizeof(Tilebuf_Rect)); r->x = cur.left; r->y = cur.top; r->w = cur.width; r->h = cur.height; rects = (Tilebuf_Rect *)eina_inlist_append(EINA_INLIST_GET(rects), EINA_INLIST_GET(r)); } } return rects; #else Tilebuf_Rect *rects = NULL; Tilebuf_Tile *tbt; int x, y; tbt = &(TILE(tb, 0, 0)); for (y = 0; y < tb->tiles.h; y++) { for (x = 0; x < tb->tiles.w; x++, tbt++) { if (tbt->redraw) { Tilebuf_Tile *tbti; int can_expand_x = 1, can_expand_y = 1; Tilebuf_Rect *r = NULL; int xx = 0, yy = 0; r = malloc(sizeof(Tilebuf_Rect)); r->_list_data.next = NULL; r->_list_data.prev = NULL; r->_list_data.last = NULL; /* amalgamate tiles */ #if 1 tbti = tbt; while (can_expand_x) { tbti++; xx++; if ((x + xx) >= tb->tiles.w) can_expand_x = 0; else if (!(tbti->redraw)) can_expand_x = 0; if (can_expand_x) tbti->redraw = 0; } tbti = tbt; while (can_expand_y) { int i; tbti += tb->tiles.w; yy++; if ((y + yy) >= tb->tiles.h) can_expand_y = 0; if (can_expand_y) { Tilebuf_Tile *tbtj; tbtj = tbti; for (i = x; i < x + xx; i++, tbtj++) { if (!(tbtj->redraw)) { can_expand_y = 0; break; } } } if (can_expand_y) { Tilebuf_Tile *tbtj; tbtj = tbti; for (i = x; i < x + xx; i++, tbtj++) tbtj->redraw = 0; } } tbt->redraw = 0; #else xx = 1; yy = 1; #endif r->x = x * tb->tile_size.w; r->y = y * tb->tile_size.h; r->w = (xx) * tb->tile_size.w; r->h = (yy) * tb->tile_size.h; rects = eina_inlist_append(rects, r); x = x + (xx - 1); tbt += xx - 1; } } } return rects; #endif }
EAPI int evas_common_tilebuf_add_redraw(Tilebuf *tb, int x, int y, int w, int h) { #ifdef RECTUPDATE /* int i; if ((w <= 0) || (h <= 0)) return 0; RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h); if ((w <= 0) || (h <= 0)) return 0; for (i = 0; i < h; i++) evas_common_regionbuf_span_add(tb->rb, x, x + w - 1, y + i); return 1; */ #elif defined(EVAS_RECT_SPLIT) if ((w <= 0) || (h <= 0)) return 0; RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h); if ((w <= 0) || (h <= 0)) return 0; // optimize a common case -> adding the exact same rect 2x in a row if ((tb->prev_add.x == x) && (tb->prev_add.y == y) && (tb->prev_add.w == w) && (tb->prev_add.h == h)) return 1; tb->prev_add.x = x; tb->prev_add.y = y; tb->prev_add.w = w; tb->prev_add.h = h; tb->prev_del.w = 0; tb->prev_del.h = 0; return _add_redraw(&tb->rects, x, y, w, h); #else /* int tx1, tx2, ty1, ty2, tfx1, tfx2, tfy1, tfy2, xx, yy; int num; if ((w <= 0) || (h <= 0)) return 0; RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h); if ((w <= 0) || (h <= 0)) return 0; num = 0; // wipes out any motion vectors in tiles it touches into redraws if (tilebuf_x_intersect(tb, x, w, &tx1, &tx2, &tfx1, &tfx2) && tilebuf_y_intersect(tb, y, h, &ty1, &ty2, &tfy1, &tfy2)) { Tilebuf_Tile *tbt; int delta_x; int delta_y; tbt = &(TILE(tb, tx1, ty1)); delta_x = tx2 - tx1 + 1; delta_y = ty2 - ty1 + 1; for (yy = delta_y; yy > 0; yy--) { Tilebuf_Tile *tbti; tbti = tbt; for (xx = delta_x; xx > 0; xx--) { tbti->redraw = 1; tbti++; } tbt += tb->tiles.w; } num = (tx2 - tx1 + 1) * (ty2 - ty1 + 1); } return num; */ #endif }
EAPI int evas_common_tilebuf_del_redraw(Tilebuf *tb, int x, int y, int w, int h) { #ifdef RECTUPDATE /* int i; for (i = 0; i < h; i++) evas_common_regionbuf_span_del(tb->rb, x, x + w - 1, y + i); */ #elif defined(EVAS_RECT_SPLIT) rect_t r; if (!tb->rects.head) return 0; if ((w <= 0) || (h <= 0)) return 0; RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h); if ((w <= 0) || (h <= 0)) return 0; /* we dont need to do this fuzz stuff - it actually creates overdraw bugs * when evas shouldnt draw at all. x += 1; y += 1; x >>= 1; y >>= 1; w -= 1; w >>= 1; h -= 1; h >>= 1; if ((w <= 0) || (h <= 0)) return 0; */ // optimize a common case -> deleting the exact same rect 2x in a row if ((tb->prev_del.x == x) && (tb->prev_del.y == y) && (tb->prev_del.w == w) && (tb->prev_del.h == h)) return 1; tb->prev_del.x = x; tb->prev_del.y = y; tb->prev_del.w = w; tb->prev_del.h = h; tb->prev_add.w = 0; tb->prev_add.h = 0; rect_init(&r, x, y, w, h); rect_list_del_split_strict(&tb->rects, r); tb->need_merge = 1; return 0; #else /* int tx1, tx2, ty1, ty2, tfx1, tfx2, tfy1, tfy2, xx, yy; int num; num = 0; // wipes out any motion vectors in tiles it touches into redraws if (tilebuf_x_intersect(tb, x, w, &tx1, &tx2, &tfx1, &tfx2) && tilebuf_y_intersect(tb, y, h, &ty1, &ty2, &tfy1, &tfy2)) { Tilebuf_Tile *tbt; int delta_y; int delta_x; if (!tfx1) tx1++; if (!tfx2) tx2--; if (!tfy1) ty1++; if (!tfy2) ty2--; tbt = &(TILE(tb, tx1, ty1)); delta_x = tx2 - tx1 + 1; delta_y = ty2 - ty1 + 1; for (yy = delta_y; yy > 0; yy--) { Tilebuf_Tile *tbti; tbti = tbt; for (xx = delta_x; xx > 0; xx--) { tbti->redraw = 0; tbti++; } tbt += tb->tiles.w; } num = (tx2 - tx1 + 1) * (ty2 - ty1 + 1); } return num; */ #endif }
void * evas_software_xcb_outbuf_new_region_for_update(Outbuf *buf, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch) { RGBA_Image *im = NULL; Outbuf_Region *obr = NULL; Eina_Bool use_shm = EINA_TRUE; Eina_Bool alpha = EINA_FALSE; int bpl = 0; if ((buf->onebuf) && (buf->priv.x11.xcb.shm)) { Eina_Rectangle *rect; RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, buf->w, buf->h); if (!(obr = calloc(1, sizeof(Outbuf_Region)))) return NULL; if (!(rect = eina_rectangle_new(x, y, w, h))) { free(obr); return NULL; } if ((eina_array_push(&buf->priv.onebuf_regions, rect)) && (buf->priv.onebuf)) { if (cx) *cx = x; if (cy) *cy = y; if (cw) *cw = w; if (ch) *ch = h; if (!buf->priv.synced) { _xcbob_sync(buf->priv.x11.xcb.conn); buf->priv.synced = EINA_TRUE; } free(obr); return buf->priv.onebuf; } obr->x = 0; obr->y = 0; obr->w = buf->w; obr->h = buf->h; if (cx) *cx = x; if (cy) *cy = y; if (cw) *cw = w; if (ch) *ch = h; alpha = ((buf->priv.x11.xcb.mask) || (buf->priv.destination_alpha)); use_shm = buf->priv.x11.xcb.shm; if ((buf->rot == 0) && (buf->priv.x11.xcb.imdepth == 32) && (buf->priv.mask.r == 0xff0000) && (buf->priv.mask.g == 0x00ff00) && (buf->priv.mask.b == 0x0000ff)) { obr->xcbob = evas_software_xcb_output_buffer_new(buf->priv.x11.xcb.conn, buf->priv.x11.xcb.visual, buf->priv.x11.xcb.depth, buf->w, buf->h, use_shm, NULL); if (!obr->xcbob) { free(obr); return NULL; } #ifdef EVAS_CSERVE2 if (evas_cserve2_use_get()) { im = (RGBA_Image *)evas_cache2_image_data(evas_common_image_cache2_get(), buf->w, buf->h, (DATA32 *)evas_software_xcb_output_buffer_data(obr->xcbob, &bpl), alpha, EVAS_COLORSPACE_ARGB8888); } else #endif { im = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(), buf->w, buf->h, (DATA32 *)evas_software_xcb_output_buffer_data(obr->xcbob, &bpl), alpha, EVAS_COLORSPACE_ARGB8888); } if (!im) { evas_software_xcb_output_buffer_free(obr->xcbob, EINA_FALSE); free(obr); return NULL; } im->extended_info = obr; if (buf->priv.x11.xcb.mask) { obr->mask = evas_software_xcb_output_buffer_new(buf->priv.x11.xcb.conn, buf->priv.x11.xcb.visual, 1, buf->w, buf->h, use_shm, NULL); } } else { int bw = 0, bh = 0; #ifdef EVAS_CSERVE2 if (evas_cserve2_use_get()) { im = (RGBA_Image *)evas_cache2_image_empty(evas_common_image_cache2_get()); } else #endif { im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get()); } if (!im) { free(obr); return NULL; } im->cache_entry.flags.alpha |= (alpha ? 1 : 0); #ifdef EVAS_CSERVE2 if (evas_cserve2_use_get()) evas_cache2_image_surface_alloc(&im->cache_entry, buf->w, buf->h); else #endif evas_cache_image_surface_alloc(&im->cache_entry, buf->w, buf->h); im->extended_info = obr; if ((buf->rot == 0) || (buf->rot == 180)) { bw = buf->w; bh = buf->h; } else if ((buf->rot == 90) || (buf->rot == 270)) { bw = buf->h; bh = buf->w; } obr->xcbob = evas_software_xcb_output_buffer_new(buf->priv.x11.xcb.conn, buf->priv.x11.xcb.visual, buf->priv.x11.xcb.depth, bw, bh, use_shm, NULL); if (!obr->xcbob) { #ifdef EVAS_CSERVE2 if (evas_cserve2_use_get()) evas_cache2_image_close(&im->cache_entry); else #endif evas_cache_image_drop(&im->cache_entry); free(obr); return NULL; } if (buf->priv.x11.xcb.mask) { obr->mask = evas_software_xcb_output_buffer_new(buf->priv.x11.xcb.conn, buf->priv.x11.xcb.visual, 1, bw, bh, use_shm, NULL); } } /* FIXME: We should be able to remove this memset. */ if ((alpha) && (im->image.data)) { /* FIXME: Faster memset */ // memset(im->image.data, 0, (w * h * sizeof(DATA32))); } buf->priv.onebuf = im; return im; } if (!(obr = calloc(1, sizeof(Outbuf_Region)))) return NULL; obr->x = x; obr->y = y; obr->w = w; obr->h = h; if (cx) *cx = 0; if (cy) *cy = 0; if (cw) *cw = w; if (ch) *ch = h; use_shm = buf->priv.x11.xcb.shm; alpha = ((buf->priv.x11.xcb.mask) || (buf->priv.destination_alpha)); if ((buf->rot == 0) && (buf->priv.x11.xcb.imdepth == 32) && (buf->priv.mask.r == 0xff0000) && (buf->priv.mask.g == 0x00ff00) && (buf->priv.mask.b == 0x0000ff)) { obr->xcbob = _find_xcbob(buf->priv.x11.xcb.conn, buf->priv.x11.xcb.visual, buf->priv.x11.xcb.depth, w, h, use_shm, NULL); if (!obr->xcbob) { free(obr); return NULL; } #ifdef EVAS_CSERVE2 if (evas_cserve2_use_get()) { im = (RGBA_Image *)evas_cache2_image_data(evas_common_image_cache2_get(), w, h, (DATA32 *)evas_software_xcb_output_buffer_data(obr->xcbob, &bpl), alpha, EVAS_COLORSPACE_ARGB8888); } else #endif { im = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(), w, h, (DATA32 *)evas_software_xcb_output_buffer_data(obr->xcbob, &bpl), alpha, EVAS_COLORSPACE_ARGB8888); } if (!im) { _unfind_xcbob(obr->xcbob, EINA_FALSE); free(obr); return NULL; } im->extended_info = obr; if (buf->priv.x11.xcb.mask) { obr->mask = _find_xcbob(buf->priv.x11.xcb.conn, buf->priv.x11.xcb.visual, 1, w, h, use_shm, NULL); } } else { int bw = 0, bh = 0; #ifdef EVAS_CSERVE2 if (evas_cserve2_use_get()) { im = (RGBA_Image *)evas_cache2_image_empty(evas_common_image_cache2_get()); } else #endif { im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get()); } if (!im) { free(obr); return NULL; } im->cache_entry.flags.alpha |= (alpha ? 1 : 0); #ifdef EVAS_CSERVE2 if (evas_cserve2_use_get()) evas_cache2_image_surface_alloc(&im->cache_entry, w, h); else #endif evas_cache_image_surface_alloc(&im->cache_entry, w, h); im->extended_info = obr; if ((buf->rot == 0) || (buf->rot == 180)) { bw = w; bh = h; } else if ((buf->rot == 90) || (buf->rot == 270)) { bw = h; bh = w; } obr->xcbob = _find_xcbob(buf->priv.x11.xcb.conn, buf->priv.x11.xcb.visual, buf->priv.x11.xcb.depth, bw, bh, use_shm, NULL); if (!obr->xcbob) { #ifdef EVAS_CSERVE2 if (evas_cserve2_use_get()) evas_cache2_image_close(&im->cache_entry); else #endif evas_cache_image_drop(&im->cache_entry); free(obr); return NULL; } if (buf->priv.x11.xcb.mask) { obr->mask = _find_xcbob(buf->priv.x11.xcb.conn, buf->priv.x11.xcb.visual, 1, bw, bh, use_shm, NULL); } } /* FIXME: We should be able to remove this memset. */ if (((buf->priv.x11.xcb.mask) || (buf->priv.destination_alpha)) && (im->image.data)) { /* FIXME: Faster memset */ // memset(im->image.data, 0, (w * h * sizeof(DATA32))); } buf->priv.pending_writes = eina_list_append(buf->priv.pending_writes, im); return im; }