Skip to content

Instantly share code, notes, and snippets.

@jonny-novikov
Last active August 29, 2015 14:24
Show Gist options
  • Select an option

  • Save jonny-novikov/e4779619298a856abfc1 to your computer and use it in GitHub Desktop.

Select an option

Save jonny-novikov/e4779619298a856abfc1 to your computer and use it in GitHub Desktop.
static void inner_stretch_argb8888_bilinear(Blitter* blitter, const InnerInfo* info)
{
uint32 u = info->ustart;
uint32 vfrac2 = info->vfrac >> 8;
uint32 vfrac1 = 0x100 - vfrac2;
uint32* src1 = reinterpret_cast<uint32*>(info->src);
uint32* src2 = reinterpret_cast<uint32*>(info->src2);
uint32* dest = reinterpret_cast<uint32*>(info->dest);
int count = info->width;
while ( count-- )
{
uint32 uinte = (u >> 16);
uint32 ufrac2 = (u & 0xff00) >> 8;
uint32 ufrac1 = 0x100 - ufrac2;
uint32 pix11a = src1[uinte];
uint32 pix12a = src1[uinte + 1];
uint32 pix21a = src2[uinte];
uint32 pix22a = src2[uinte + 1];
uint32 pix11b = pix11a & 0x00ff00ff;
uint32 pix12b = pix12a & 0x00ff00ff;
uint32 pix21b = pix21a & 0x00ff00ff;
uint32 pix22b = pix22a & 0x00ff00ff;
pix11a = (pix11a & 0xff00ff00) >> 8;
pix12a = (pix12a & 0xff00ff00) >> 8;
pix21a = (pix21a & 0xff00ff00) >> 8;
pix22a = (pix22a & 0xff00ff00) >> 8;
uint32 col1ag = ((ufrac1 * pix11a + ufrac2 * pix12a) & 0xff00ff00) >> 8;
uint32 col2ag = ((ufrac1 * pix21a + ufrac2 * pix22a) & 0xff00ff00) >> 8;
uint32 col1rb = ((ufrac1 * pix11b + ufrac2 * pix12b) & 0xff00ff00) >> 8;
uint32 col2rb = ((ufrac1 * pix21b + ufrac2 * pix22b) & 0xff00ff00) >> 8;
*dest++ = (((vfrac1 * col1ag + vfrac2 * col2ag) & 0xff00ff00))
| (((vfrac1 * col1rb + vfrac2 * col2rb) & 0xff00ff00) >> 8);
u += info->ustep;
}
}
void Surface::BlitImage(const Surface& source, BlitMode mode)
{
// validate surfaces
if ( !(width && height && image && source.width && source.height && source.image) )
return;
bool resize = width != source.width || height != source.height;
// choose blitter mode
int type = 0;
if ( source.format != format ) type |= BLIT_REMAP;
if ( mode==BLIT_SCALE && resize ) type |= BLIT_STRETCH;
if ( mode==BLIT_BILINEAR_SCALE && resize ) type |= BLIT_BILINEAR | BLIT_STRETCH;
// plain row-by-row copying if !conversion && !stretching
if ( !type )
{
int minwidth = MIN(width,source.width);
int minheight = MIN(height,source.height);
int length = minwidth * format.GetBytes();
uint8* s = source.image;
uint8* d = image;
for ( int y=0; y<minheight; ++y )
{
memcpy(d,s,length);
s += source.pitch;
d += pitch;
}
}
else
{
// delegate the workload for floating-point blitting module
// if either source or destination pixelformat is floating-point
if ( format.IsFloat() || source.format.IsFloat() )
{
BlitImageFloat(source,mode);
return;
}
// get a suitable blitter
Blitter* blitter = GetBlitter(format,source.format,type);
if ( !blitter )
return;
InnerInfo innerinfo;
innerinfo.dest = reinterpret_cast<uint8*>(image);
// stretching
if ( blitter->convtype & BLIT_STRETCH )
{
uint32 vstep,v;
// bilinear stretch has special UV calculations
if ( blitter->convtype & BLIT_BILINEAR )
{
if ( width < source.width )
{
innerinfo.ustep = (source.width << 16) / width;
innerinfo.ustart = (innerinfo.ustep >> 1) - 0x8000;
}
else
{
int div = width - 1;
if ( !div ) div = 1;
innerinfo.ustep = ((source.width - 1) << 16) / div;
innerinfo.ustart = 0;
}
if ( height < source.height )
{
vstep = (source.height << 16) / height;
v = (vstep >> 1) - 0x8000;
}
else
{
int div = height - 1;
if ( !div ) div = 1;
vstep = ((source.height - 1) << 16) / div;
v = 0;
}
}
else // !bilinear
{
innerinfo.ustep = (source.width << 16) / width;
innerinfo.ustart = (innerinfo.ustep >> 1);
vstep = (source.height << 16) / height;
v = vstep >> 1;
}
innerinfo.width = width;
for ( int y=0; y<height; ++y )
{
innerinfo.src = reinterpret_cast<uint8*>(source.image) + ((v >> 16) * source.pitch);
innerinfo.src2 = innerinfo.src + source.pitch;
// clamp lower scanline - just in case
// the delta calculation above should ensure this is not required,
// but, rgb888_bilinear innerloops pagefault -- fix this performance/quality
// caveat sometime. ;-)
if ( y == (height - 1) )
innerinfo.src2 = innerinfo.src;
innerinfo.vfrac = v & 0xffff;
blitter->Blit(&innerinfo);
v += vstep;
innerinfo.dest += pitch;
}
}
else // conversion && !stretching
{
int minwidth = MIN(width,source.width);
int minheight = MIN(height,source.height);
innerinfo.width = minwidth;
innerinfo.src = reinterpret_cast<uint8*>(source.image);
for ( int y=0; y<minheight; ++y )
{
blitter->Blit(&innerinfo);
innerinfo.dest += pitch;
innerinfo.src += source.pitch;
}
}
}
}
//-----------------------------------------------------------------------
// Область для рисования
//-----------------------------------------------------------------------
struct SurfaceDesc
{
public:
typedef iml::core::PixelFormat PixFormat_t;
typedef iml::uint8 byte;
SurfaceDesc()
: width(0),height(0),pitch(0),image(NULL)
{
}
SurfaceDesc(int w, int h, int p, const PixFormat_t& pxf, void* i)
: width(w),height(h),pitch(p),format(pxf),image(reinterpret_cast<byte*>(i))
{
IMLASSERT( width > 0 && height > 0 );
}
SurfaceDesc(const SurfaceDesc& desc)
: width(desc.width),height(desc.height),pitch(desc.pitch),format(desc.format),image(desc.image)
{
IMLASSERT( width > 0 && height > 0 );
}
int GetWidth() const
{
return width;
}
int GetHeight() const
{
return height;
}
int GetPitch() const
{
return pitch;
}
const PixFormat_t& GetPixelFormat() const
{
return format;
}
byte* GetImage() const
{
return image;
}
Size_i GetSize() const
{
return Size_i(width, height);
}
Rect_i GetRect() const
{
return Rect_i(0,0,width,height);
}
SurfaceDesc GetSurfacePart(const Rect_i& rect) const
{
// clip
Rect_i q;
if ( !Rect_i::Intersect(q, GetRect(), rect) )
return *this;
SurfaceDesc surface;
surface.width = q.right - q.left;
surface.height = q.bottom - q.top;
surface.pitch = pitch;
surface.format = format;
surface.image = image + q.top * pitch + q.left * format.GetBytes();
return surface;
}
protected:
int width; // width in pixels
int height; // height in pixels
int pitch; // width in bytes
PixFormat_t format; // pixel format
byte* image; // image pointer
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment