blob: 59f43ef487013a8cf57ba3774445a9a0952292d9 [file] [log] [blame]
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <system/graphics.h>
#include <hardware/exynos/ion.h>
#include "log.h"
#include "buffer.h"
#define NR_EXTRA_PIXELS 128
void Buffer::init(int buffer[], unsigned int count, unsigned int fmt, unsigned int width, unsigned int height)
{
mBuffer[0] = buffer[0];
mCount++;
if (fmt != HAL_PIXEL_FORMAT_YCBCR_422_I) { // NV12
if (count > 1) {
mBuffer[1] = buffer[1];
} else {
mBuffer[1] = mBuffer[0];
mOffset[1] = width * height;
}
mCount++;
} else { // YUYV
mHBitPP[0] = 16;
mVBitPP[0] = 8;
mHBitPP[1] = 0;
mVBitPP[1] = 0;
}
}
// allocates bounce buffers when a job needs to scaling more than once.
// we only allocate a single bounce buffer since we does not use multi-planar format
// between the scaling even thoug the source image or the final destination image are
// multi-planar format.
int Buffer::alloc(unsigned int fmt, unsigned int width, unsigned int height)
{
int devfd = exynos_ion_open();
if (devfd < 0)
return -1;
// MSCL may read extra 128 pixels after the image region of interest due to its performance.
// So, we should feed MSCL H/W more memory not to cause buffer overrun.
size_t len = width * height + NR_EXTRA_PIXELS;
if (fmt == HAL_PIXEL_FORMAT_YCBCR_422_I) {
len += len + NR_EXTRA_PIXELS;
} else {
len += len / 2;
}
int buffd = exynos_ion_alloc(devfd, len, 1, 0);
if (buffd < 0)
ALOGERR("failed to allocate for %ux%u (fmt %#x)", width, height ,fmt);
exynos_ion_close(devfd);
return buffd;
}
Buffer::~Buffer()
{
if (mAllocated && (mBuffer[0] >= 0))
close(mBuffer[0]);
}
int Buffer::getByteOffset(unsigned int idx, unsigned int x_offset, unsigned int y_offset, unsigned int pixel_stride) const
{
if (idx < mCount) {
unsigned int byte_stride = pixel_stride * mHBitPP[idx] / 8;
return mOffset[idx] + (y_offset * mVBitPP[idx] * byte_stride + x_offset * mHBitPP[idx]) / 8;
}
return 0;
}