forked from enlightenment/efl
Brand new DirectFB engine.
ProFUSION funded the rework of DirectFB engine, it works quite well, please report problems with it and be sure to try to uncomment the following lines to see if it helps: evas_engine.c: (uncomment if you notice problems) //#define DFB_USE_EVAS_IMAGE_DRAW 1 //#define DFB_USE_EVAS_RECT_DRAW 1 //#define DFB_USE_EVAS_POLYGON_DRAW 1 //#define DFB_UPDATE_INDIVIDUAL_RECTS 1 polygon.c: (comment if you notice slowdowns, but may lead to visual problems) #define USE_SPAN_RECTS 1 You can also turn on debug by uncommenting in evas_engine.c: //#define DFB_DEBUG_IMAGE 1 //#define DFB_DEBUG_FLAGS 1 //#define DFB_DEBUG_ACCELERATION 1 Thanks to Denis Oliver Kropp (dok) for review and patches! SVN revision: 35904
This commit is contained in:
parent
d06c5e9efb
commit
c1c8a18b54
|
@ -88,9 +88,9 @@ if BUILD_ENGINE_SOFTWARE_XCB
|
||||||
psoftwarexcb = evas-software-xcb.pc
|
psoftwarexcb = evas-software-xcb.pc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#if BUILD_ENGINE_DIRECTFB
|
if BUILD_ENGINE_DIRECTFB
|
||||||
#pdirectfb = evas-directfb.pc
|
pdirectfb = evas-directfb.pc
|
||||||
#endif
|
endif
|
||||||
|
|
||||||
if BUILD_ENGINE_FB
|
if BUILD_ENGINE_FB
|
||||||
pfb = evas-fb.pc
|
pfb = evas-fb.pc
|
||||||
|
|
|
@ -405,30 +405,30 @@ AM_CONDITIONAL(BUILD_ENGINE_SOFTWARE_XCB, test "x$have_evas_software_xcb" = "xye
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
## Check if we should build the directfb engine
|
## Check if we should build the directfb engine
|
||||||
#want_evas_directfb="no";
|
want_evas_directfb="no";
|
||||||
#have_evas_directfb="no";
|
have_evas_directfb="no";
|
||||||
#
|
|
||||||
#AC_MSG_CHECKING(whether directfb backend is to be built)
|
AC_MSG_CHECKING(whether directfb backend is to be built)
|
||||||
#AC_ARG_ENABLE(directfb,
|
AC_ARG_ENABLE(directfb,
|
||||||
# AC_HELP_STRING([--enable-directfb], [enable the DirectFB rendering backend]),
|
AC_HELP_STRING([--enable-directfb], [enable the DirectFB rendering backend]),
|
||||||
# [ want_evas_directfb=$enableval ]
|
[ want_evas_directfb=$enableval ]
|
||||||
#)
|
)
|
||||||
#AC_MSG_RESULT($want_evas_directfb)
|
AC_MSG_RESULT($want_evas_directfb)
|
||||||
#
|
|
||||||
#if test "x$want_evas_directfb" = "xyes"; then
|
if test "x$want_evas_directfb" = "xyes"; then
|
||||||
# PKG_CHECK_MODULES(DIRECTFB, directfb >= 0.9.16,
|
PKG_CHECK_MODULES(DIRECTFB, directfb >= 0.9.16,
|
||||||
# [
|
[
|
||||||
# AC_DEFINE(BUILD_ENGINE_DIRECTFB, 1, [DirectFB Rendering Backend])
|
AC_DEFINE(BUILD_ENGINE_DIRECTFB, 1, [DirectFB Rendering Backend])
|
||||||
# have_evas_directfb="yes"
|
have_evas_directfb="yes"
|
||||||
# ],
|
],
|
||||||
# [
|
[
|
||||||
# if test "x$want_evas_directfb" = "xyes" -a "x$use_strict" = "xyes" ; then
|
if test "x$want_evas_directfb" = "xyes" -a "x$use_strict" = "xyes" ; then
|
||||||
# AC_MSG_ERROR([DirectFB not found (strict dependencies checking)])
|
AC_MSG_ERROR([DirectFB not found (strict dependencies checking)])
|
||||||
# fi
|
fi
|
||||||
# ]
|
]
|
||||||
# )
|
)
|
||||||
#fi
|
fi
|
||||||
#AM_CONDITIONAL(BUILD_ENGINE_DIRECTFB, test "x$have_evas_directfb" = "xyes")
|
AM_CONDITIONAL(BUILD_ENGINE_DIRECTFB, test "x$have_evas_directfb" = "xyes")
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
## Check if we should build the sdl engine
|
## Check if we should build the sdl engine
|
||||||
|
@ -1653,6 +1653,7 @@ AC_SUBST(pthread_libs)
|
||||||
AC_OUTPUT([
|
AC_OUTPUT([
|
||||||
Makefile
|
Makefile
|
||||||
evas-cairo-x11.pc
|
evas-cairo-x11.pc
|
||||||
|
evas-directfb.pc
|
||||||
evas-fb.pc
|
evas-fb.pc
|
||||||
evas-glitz-x11.pc
|
evas-glitz-x11.pc
|
||||||
evas-opengl-glew.pc
|
evas-opengl-glew.pc
|
||||||
|
@ -1698,6 +1699,7 @@ src/modules/engines/fb/Makefile
|
||||||
src/modules/engines/buffer/Makefile
|
src/modules/engines/buffer/Makefile
|
||||||
src/modules/engines/software_win32_gdi/Makefile
|
src/modules/engines/software_win32_gdi/Makefile
|
||||||
src/modules/engines/software_qtopia/Makefile
|
src/modules/engines/software_qtopia/Makefile
|
||||||
|
src/modules/engines/directfb/Makefile
|
||||||
src/modules/engines/gl_common/Makefile
|
src/modules/engines/gl_common/Makefile
|
||||||
src/modules/engines/gl_glew/Makefile
|
src/modules/engines/gl_glew/Makefile
|
||||||
src/modules/engines/gl_x11/Makefile
|
src/modules/engines/gl_x11/Makefile
|
||||||
|
@ -1764,6 +1766,7 @@ echo " Software 16bit X11.........: $have_evas_software_16_x11"
|
||||||
echo " Software 16bit Directdraw..: $have_evas_software_16_ddraw"
|
echo " Software 16bit Directdraw..: $have_evas_software_16_ddraw"
|
||||||
echo " Software 16bit WinCE.......: $have_evas_software_16_wince"
|
echo " Software 16bit WinCE.......: $have_evas_software_16_wince"
|
||||||
echo " Software 16bit SDL.........: $have_evas_sdl (primitive: $sdl_primitive)"
|
echo " Software 16bit SDL.........: $have_evas_sdl (primitive: $sdl_primitive)"
|
||||||
|
echo " DirectFB...................: $have_evas_directfb"
|
||||||
# FIXME: opengl engine needs to be fixed and tested lots for all drivers
|
# FIXME: opengl engine needs to be fixed and tested lots for all drivers
|
||||||
# FIXME: xrender engine to be written
|
# FIXME: xrender engine to be written
|
||||||
echo
|
echo
|
||||||
|
|
|
@ -5,6 +5,7 @@ software_generic \
|
||||||
buffer \
|
buffer \
|
||||||
cairo_common \
|
cairo_common \
|
||||||
cairo_x11 \
|
cairo_x11 \
|
||||||
|
directfb \
|
||||||
fb \
|
fb \
|
||||||
gl_common \
|
gl_common \
|
||||||
gl_x11 \
|
gl_x11 \
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef _EVAS_ENGINE_DIRECTFB_H
|
||||||
|
#define _EVAS_ENGINE_DIRECTFB_H
|
||||||
|
|
||||||
|
#include <Evas.h>
|
||||||
|
#include <directfb/directfb.h>
|
||||||
|
|
||||||
|
typedef struct _Evas_Engine_Info_DirectFB Evas_Engine_Info_DirectFB;
|
||||||
|
|
||||||
|
struct _Evas_Engine_Info_DirectFB
|
||||||
|
{
|
||||||
|
/* PRIVATE - don't mess with this baby or evas will poke its tongue out */
|
||||||
|
/* at you and make nasty noises */
|
||||||
|
Evas_Engine_Info magic;
|
||||||
|
|
||||||
|
struct Evas_Engine_DirectFB_Spec {
|
||||||
|
IDirectFB *dfb;
|
||||||
|
IDirectFBSurface *surface;
|
||||||
|
} info;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
MAINTAINERCLEANFILES = Makefile.in
|
||||||
|
|
||||||
|
AM_CPPFLAGS = \
|
||||||
|
-I. \
|
||||||
|
-I$(top_srcdir)/src/lib \
|
||||||
|
-I$(top_srcdir)/src/lib/include \
|
||||||
|
-I$(top_srcdir)/src/modules/engines \
|
||||||
|
@FREETYPE_CFLAGS@ \
|
||||||
|
@DIRECTFB_CFLAGS@
|
||||||
|
|
||||||
|
AM_CFLAGS = @WIN32_CFLAGS@
|
||||||
|
|
||||||
|
if BUILD_ENGINE_DIRECTFB
|
||||||
|
|
||||||
|
pkgdir = $(libdir)/evas/modules/engines/directfb/$(MODULE_ARCH)
|
||||||
|
|
||||||
|
pkg_LTLIBRARIES = module.la
|
||||||
|
|
||||||
|
module_la_SOURCES = evas_engine.c polygon.c
|
||||||
|
|
||||||
|
module_la_LIBADD = @DIRECTFB_LIBS@ $(top_builddir)/src/lib/libevas.la
|
||||||
|
module_la_LDFLAGS = @lt_no_undefined@ -module -avoid-version
|
||||||
|
module_la_LIBTOOLFLAGS = --tag=disable-static
|
||||||
|
module_la_DEPENDENCIES = $(top_builddir)/config.h
|
||||||
|
|
||||||
|
include_HEADERS = Evas_Engine_DirectFB.h
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
EXTRA_DIST = evas_engine.h
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef EVAS_ENGINE_DIRECTFB_H
|
||||||
|
#define EVAS_ENGINE_DIRECTFB_H
|
||||||
|
|
||||||
|
#include "evas_common.h"
|
||||||
|
#include "evas_private.h"
|
||||||
|
#include "Evas_Engine_DirectFB.h"
|
||||||
|
|
||||||
|
typedef struct _DirectFB_Engine_Image_Entry DirectFB_Engine_Image_Entry;
|
||||||
|
struct _DirectFB_Engine_Image_Entry
|
||||||
|
{
|
||||||
|
Engine_Image_Entry cache_entry;
|
||||||
|
IDirectFBSurface *surface;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
Evas_Bool engine_surface : 1;
|
||||||
|
Evas_Bool is_locked : 1;
|
||||||
|
} flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _Render_Engine Render_Engine;
|
||||||
|
struct _Render_Engine
|
||||||
|
{
|
||||||
|
DirectFB_Engine_Image_Entry *screen_image;
|
||||||
|
const struct Evas_Engine_DirectFB_Spec *spec;
|
||||||
|
IDirectFB *dfb;
|
||||||
|
|
||||||
|
Evas_Cache_Engine_Image *cache;
|
||||||
|
|
||||||
|
Tilebuf *tb;
|
||||||
|
Tilebuf_Rect *rects;
|
||||||
|
Evas_Object_List *cur_rect;
|
||||||
|
|
||||||
|
DFBRegion *update_regions;
|
||||||
|
unsigned int update_regions_count;
|
||||||
|
unsigned int update_regions_limit;
|
||||||
|
|
||||||
|
Evas_Bool end : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
int _dfb_surface_set_color_from_context(IDirectFBSurface *surface, RGBA_Draw_Context *dc);
|
||||||
|
void _dfb_polygon_draw(IDirectFBSurface *surface, RGBA_Draw_Context *dc, Evas_Object_List *points);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,270 @@
|
||||||
|
#include <math.h>
|
||||||
|
#include "evas_engine.h"
|
||||||
|
|
||||||
|
/* Work around bug in DirectFB FillSpans(), but uses twice as much memory */
|
||||||
|
#define USE_SPAN_RECTS 1
|
||||||
|
|
||||||
|
#define MAX_SPANS 512
|
||||||
|
typedef struct _RGBA_Edge RGBA_Edge;
|
||||||
|
typedef struct _RGBA_Vertex RGBA_Vertex;
|
||||||
|
|
||||||
|
struct _RGBA_Edge
|
||||||
|
{
|
||||||
|
double x, dx;
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _RGBA_Vertex
|
||||||
|
{
|
||||||
|
double x, y;
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define POLY_EDGE_DEL(_i) \
|
||||||
|
{ \
|
||||||
|
int _j; \
|
||||||
|
\
|
||||||
|
for (_j = 0; (_j < num_active_edges) && (edges[_j].i != _i); _j++); \
|
||||||
|
if (_j < num_active_edges) \
|
||||||
|
{ \
|
||||||
|
num_active_edges--; \
|
||||||
|
memmove(&(edges[_j]), &(edges[_j + 1]), \
|
||||||
|
(num_active_edges - _j) * sizeof(RGBA_Edge)); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define POLY_EDGE_ADD(_i, _y) \
|
||||||
|
{ \
|
||||||
|
int _j; \
|
||||||
|
float _dx; \
|
||||||
|
RGBA_Vertex *_p, *_q; \
|
||||||
|
if (_i < (n - 1)) _j = _i + 1; \
|
||||||
|
else _j = 0; \
|
||||||
|
if (point[_i].y < point[_j].y) \
|
||||||
|
{ \
|
||||||
|
_p = &(point[_i]); \
|
||||||
|
_q = &(point[_j]); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
_p = &(point[_j]); \
|
||||||
|
_q = &(point[_i]); \
|
||||||
|
} \
|
||||||
|
edges[num_active_edges].dx = _dx = (_q->x - _p->x) / (_q->y - _p->y); \
|
||||||
|
edges[num_active_edges].x = (_dx * ((float)_y + 0.5 - _p->y)) + _p->x; \
|
||||||
|
edges[num_active_edges].i = _i; \
|
||||||
|
num_active_edges++; \
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
polygon_point_sorter(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
RGBA_Vertex *p, *q;
|
||||||
|
|
||||||
|
p = (RGBA_Vertex *)a;
|
||||||
|
q = (RGBA_Vertex *)b;
|
||||||
|
if (p->y <= q->y) return -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
polygon_edge_sorter(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
RGBA_Edge *p, *q;
|
||||||
|
|
||||||
|
p = (RGBA_Edge *)a;
|
||||||
|
q = (RGBA_Edge *)b;
|
||||||
|
if (p->x <= q->x) return -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef USE_SPAN_RECTS
|
||||||
|
typedef DFBSpan span_t;
|
||||||
|
|
||||||
|
static void
|
||||||
|
polygon_span_add(span_t *span, int y, int x, int w)
|
||||||
|
{
|
||||||
|
span->x = x;
|
||||||
|
span->w = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
polygon_spans_fill(IDirectFBSurface *surface, int y, const span_t *spans, int n_spans)
|
||||||
|
{
|
||||||
|
surface->FillSpans(surface, y, spans, n_spans);
|
||||||
|
}
|
||||||
|
#else /* USE_SPAN_RECTS */
|
||||||
|
typedef DFBRectangle span_t;
|
||||||
|
|
||||||
|
static void
|
||||||
|
polygon_span_add(span_t *span, int y, int x, int w)
|
||||||
|
{
|
||||||
|
span->x = x;
|
||||||
|
span->y = y;
|
||||||
|
span->w = w;
|
||||||
|
span->h = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
polygon_spans_fill(IDirectFBSurface *surface, int y, const span_t *spans, int n_spans)
|
||||||
|
{
|
||||||
|
surface->FillRectangles(surface, spans, n_spans);
|
||||||
|
}
|
||||||
|
#endif /* USE_SPAN_RECTS */
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_dfb_polygon_draw(IDirectFBSurface *surface, RGBA_Draw_Context *dc, Evas_Object_List *points)
|
||||||
|
{
|
||||||
|
RGBA_Polygon_Point *pt;
|
||||||
|
RGBA_Vertex *point;
|
||||||
|
RGBA_Edge *edges;
|
||||||
|
Evas_Object_List *l;
|
||||||
|
int num_active_edges;
|
||||||
|
int n;
|
||||||
|
int i, j, k;
|
||||||
|
int y0, y1, y;
|
||||||
|
int ext_x, ext_y, ext_w, ext_h;
|
||||||
|
int *sorted_index;
|
||||||
|
|
||||||
|
ext_x = 0;
|
||||||
|
ext_y = 0;
|
||||||
|
surface->GetSize(surface, &ext_w, &ext_h);
|
||||||
|
if (dc->clip.use)
|
||||||
|
{
|
||||||
|
if (dc->clip.x > ext_x)
|
||||||
|
{
|
||||||
|
ext_w += ext_x - dc->clip.x;
|
||||||
|
ext_x = dc->clip.x;
|
||||||
|
}
|
||||||
|
if ((ext_x + ext_w) > (dc->clip.x + dc->clip.w))
|
||||||
|
{
|
||||||
|
ext_w = (dc->clip.x + dc->clip.w) - ext_x;
|
||||||
|
}
|
||||||
|
if (dc->clip.y > ext_y)
|
||||||
|
{
|
||||||
|
ext_h += ext_y - dc->clip.y;
|
||||||
|
ext_y = dc->clip.y;
|
||||||
|
}
|
||||||
|
if ((ext_y + ext_h) > (dc->clip.y + dc->clip.h))
|
||||||
|
{
|
||||||
|
ext_h = (dc->clip.y + dc->clip.h) - ext_y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((ext_w <= 0) || (ext_h <= 0)) return;
|
||||||
|
|
||||||
|
evas_common_cpu_end_opt();
|
||||||
|
|
||||||
|
if (!_dfb_surface_set_color_from_context(surface, dc))
|
||||||
|
return;
|
||||||
|
|
||||||
|
n = 0; for (l = (Evas_Object_List *)points; l; l = l->next) 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;
|
||||||
|
for (l = (Evas_Object_List *)points; l; l = l->next)
|
||||||
|
{
|
||||||
|
pt = (RGBA_Polygon_Point *)l;
|
||||||
|
point[k].x = pt->x;
|
||||||
|
point[k].y = pt->y;
|
||||||
|
point[k].i = k;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
qsort(point, n, sizeof(RGBA_Vertex), polygon_point_sorter);
|
||||||
|
for (k = 0; k < n; k++) sorted_index[k] = point[k].i;
|
||||||
|
k = 0;
|
||||||
|
for (l = (Evas_Object_List *)points; l; l = l->next)
|
||||||
|
{
|
||||||
|
pt = (RGBA_Polygon_Point *)l;
|
||||||
|
point[k].x = pt->x;
|
||||||
|
point[k].y = pt->y;
|
||||||
|
point[k].i = k;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
|
||||||
|
y0 = MAX(ext_y, ceil(point[sorted_index[0]].y - 0.5));
|
||||||
|
y1 = MIN(ext_y + ext_h - 1, floor(point[sorted_index[n - 1]].y - 0.5));
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
num_active_edges = 0;
|
||||||
|
|
||||||
|
for (y = y0; y <= y1; y++)
|
||||||
|
{
|
||||||
|
span_t spans[MAX_SPANS];
|
||||||
|
unsigned int n_spans = 0;
|
||||||
|
|
||||||
|
for (; (k < n) && (point[sorted_index[k]].y <= ((double)y + 0.5)); k++)
|
||||||
|
{
|
||||||
|
i = sorted_index[k];
|
||||||
|
|
||||||
|
if (i > 0) j = i - 1;
|
||||||
|
else j = n - 1;
|
||||||
|
if (point[j].y <= ((double)y - 0.5))
|
||||||
|
{
|
||||||
|
POLY_EDGE_DEL(j)
|
||||||
|
}
|
||||||
|
else if (point[j].y > ((double)y + 0.5))
|
||||||
|
{
|
||||||
|
POLY_EDGE_ADD(j, y)
|
||||||
|
}
|
||||||
|
if (i < (n - 1)) j = i + 1;
|
||||||
|
else j = 0;
|
||||||
|
if (point[j].y <= ((double)y - 0.5))
|
||||||
|
{
|
||||||
|
POLY_EDGE_DEL(i)
|
||||||
|
}
|
||||||
|
else if (point[j].y > ((double)y + 0.5))
|
||||||
|
{
|
||||||
|
POLY_EDGE_ADD(i, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort(edges, num_active_edges, sizeof(RGBA_Edge), polygon_edge_sorter);
|
||||||
|
|
||||||
|
for (j = 0; j < num_active_edges; j += 2)
|
||||||
|
{
|
||||||
|
int x0, x1;
|
||||||
|
|
||||||
|
x0 = ceil(edges[j].x - 0.5);
|
||||||
|
if (j < (num_active_edges - 1))
|
||||||
|
x1 = floor(edges[j + 1].x - 0.5);
|
||||||
|
else
|
||||||
|
x1 = x0;
|
||||||
|
if ((x1 >= ext_x) && (x0 < (ext_x + ext_w)) && (x0 <= x1))
|
||||||
|
{
|
||||||
|
if (n_spans == MAX_SPANS)
|
||||||
|
{
|
||||||
|
polygon_spans_fill(surface, y, spans, n_spans);
|
||||||
|
n_spans = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
polygon_span_add(spans + n_spans, y, x0, (x1 - x0) + 1);
|
||||||
|
n_spans++;
|
||||||
|
}
|
||||||
|
edges[j].x += edges[j].dx;
|
||||||
|
edges[j + 1].x += edges[j + 1].dx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n_spans)
|
||||||
|
polygon_spans_fill(surface, y, spans, n_spans);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(edges);
|
||||||
|
free(point);
|
||||||
|
free(sorted_index);
|
||||||
|
}
|
Loading…
Reference in New Issue