void bubbleSortX(void *a, size_t count, size_t size,
                int (*comp)(const void *, const void *) )
{
    size_t i, j;
    const size_t j_temp = count - 1;
    for(i = 0; i < count; ++i) {
        for(j = j_temp; j > i; --j) {
            void *current = a + j * size;
            void *prev = current - size;
            if(comp(prev, current) > 0) {
                swap_xor(prev, current, size);
            }
        }
    }
}
void optimizedBubbleSortX2(void *a, size_t count, size_t size,
                int (*comp)(const void *, const void *) )
{
    /*More optimized version based on: https://neerc.ifmo.ru/wiki/index.php?title=Сортировка_пузырьком */
    size_t i = 0;
    char t = 1;
    void *current = a;
    void *next;
    void *end;
    while(t) {
        t = 0;
        end = a + (count - i - 1) * size;
        for(current = a; current < end; current += size) {
            next = current + size;
            if(comp(current, next) > 0) {
                swap_xor(current, next, size);
                t = 1;
            }
        }
        i += 1;
    }
}
void optimizedBubbleSortX(void *a, size_t count, size_t size,
                int (*comp)(const void *, const void *) )
{
    /*Optimized version based on: https://neerc.ifmo.ru/wiki/index.php?title=Сортировка_пузырьком */
    size_t i = 0;
    size_t j = 0;
    size_t temp = 0;
    char t = 1;
    void *current;
    void *next;
    while(t) {
        t = 0;
        temp = count - i - 1;
        for(j = 0; j < temp; ++j) {
            current = a + j * size;
            next = current + size;
            if(comp(current, next) > 0) {
                swap_xor(current, next, size);
                t = 1;
            }
        }
        i += 1;
    }
}
/*!
*/
void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b ) const
{
	
	int pitch0 = RenderTarget->getDimension().Width << VIDEO_SAMPLE_GRANULARITY;
	int pitch1 = RenderTarget->getDimension().Width << 2;

	int aposx = (int) a->Pos.x;
	int aposy = (int) a->Pos.y;
	int bposx = (int) b->Pos.x;
	int bposy = (int) b->Pos.y;

	int dx = bposx - aposx;
	int dy = bposy - aposy;

	int c;
	int m;
	int d = 0;
	int run;

	tVideoSample *dst;
#ifdef USE_ZBUFFER
	fp24 *z;
#endif

	int xInc0 = 1 << VIDEO_SAMPLE_GRANULARITY;
	int yInc0 = pitch0;

	int xInc1 = 4;
	int yInc1 = pitch1;

	tVideoSample color;

#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR
	tFixPoint r0, g0, b0;
	getSample_color ( r0, g0, b0, a->Color[0] );
	color = fix_to_color ( r0, g0, b0 );
#else
	color = (tVideoSample) 0xFFFFFFFF;
#endif

	if ( dx < 0 )
	{
		xInc0 = - ( 1 << VIDEO_SAMPLE_GRANULARITY);
		xInc1 = -4;
		dx = -dx;
	}

	if ( dy > dx )
	{
		swap_xor ( dx, dy );
		swap_xor ( xInc0, yInc0 );
		swap_xor ( xInc1, yInc1 );
	}

	if ( 0 == dx )
		return;

	dst = (tVideoSample*) ( (u8*) lockedSurface + ( aposy * pitch0 ) + (aposx << VIDEO_SAMPLE_GRANULARITY ) );
#ifdef USE_ZBUFFER
	z = (fp24*) ( (u8*) lockedDepthBuffer + ( aposy * pitch1 ) + (aposx << 2 ) );
#endif

	c = dx << 1;
	m = dy << 1;

#ifdef IPOL_Z
	f32 slopeZ = (b->Pos.z - a->Pos.z) / f32(dx);
	f32 dataZ = a->Pos.z;
#endif

#ifdef IPOL_W
	fp24 slopeW = (b->Pos.w - a->Pos.w) / f32( dx );
	fp24 dataW = a->Pos.w;
#endif

	run = dx;
	while ( run )
	{
#ifdef CMP_Z
		if ( *z >= dataZ )
#endif
#ifdef CMP_W
		if ( dataW >= *z )
#endif
		{
#ifdef WRITE_Z
			*z = dataZ;
#endif
#ifdef WRITE_W
			*z = dataW;
#endif

		*dst = color;

		}

		dst = (tVideoSample*) ( (u8*) dst + xInc0 );	// x += xInc
#ifdef IPOL_Z
		z = (fp24*) ( (u8*) z + xInc1 );
#endif
#ifdef IPOL_W
		z = (fp24*) ( (u8*) z + xInc1 );
#endif

		d += m;
		if ( d > dx )
		{
			dst = (tVideoSample*) ( (u8*) dst + yInc0 );	// y += yInc
#ifdef IPOL_Z
			z = (fp24*) ( (u8*) z + yInc1 );
#endif
#ifdef IPOL_W
			z = (fp24*) ( (u8*) z + yInc1 );
#endif

			d -= c;
		}
		run -= 1;
#ifdef IPOL_Z
		dataZ += slopeZ;
#endif
#ifdef IPOL_W
		dataW += slopeW;
#endif

	}

}