//----------------------------------------------------------------------
// Copyright (C) 2006-2007 Electronic Arts    
//----------------------------------------------------------------------

#include "job_util/image_desc.h"

namespace EA { namespace Jobs {

ImageDesc::ImageRegionDesc::ImageRegionDesc() : mXOffset(0), mYOffset(0), mInPtr(0), mOutPtr(0), mBytesPerPixel(0), mBytesPerLine(0)
{
}

ImageDesc::ImageDesc(size_t width, size_t height, size_t regionWidth, size_t regionHeight) :
    ForEachDesc(sizeof(ImageDesc), sImageRegionDescIdent),
    mWidth(width),
    mHeight(height),
    mRegionWidth(regionWidth),
    mRegionHeight(regionHeight)
{
    EA_ASSERT(width != 0);
    EA_ASSERT(height != 0);
    EA_ASSERT(regionWidth != 0);
    EA_ASSERT(regionHeight != 0);
    EA_ASSERT(width % regionWidth == 0);
    EA_ASSERT(height % regionHeight == 0);

    mRowStep = width / regionWidth;
}

int ImageDesc::GetLastOffset() const
{
    return static_cast<int>(mRowStep * (mHeight / mRegionHeight)) - 1;
}


size_t ImageDesc::GetWidth() const { return mWidth; }
size_t ImageDesc::GetHeight() const { return mHeight; }
size_t ImageDesc::GetRegionWidth() const { return mRegionWidth; }
size_t ImageDesc::GetRegionHeight() const { return mRegionHeight; }

void ImageDesc::SetImage(size_t number, size_t bytesPerPixel, size_t bytesPerLine, void const * inPtr, void * outPtr)
{
    SetImage(number, 0, 0, bytesPerPixel, bytesPerLine, inPtr, outPtr);
}

void ImageDesc::SetImage(size_t number, size_t xOffset, size_t yOffset, size_t bytesPerPixel, size_t bytesPerLine, void const * inPtr, void * outPtr)
{
    EA_ASSERT(inPtr || outPtr);
    EA_ASSERT(number < sMaxImageRegionDescs);
    EA_ASSERT( (mRegionWidth * bytesPerPixel) % 16 == 0);

    ImageRegionDesc & desc = mImageRegion[number];
    desc.mInPtr = reinterpret_cast<char const *>(inPtr);
    desc.mOutPtr = reinterpret_cast<char *>(outPtr);
    desc.mXOffset = xOffset;
    desc.mYOffset = yOffset;
    desc.mBytesPerPixel = bytesPerPixel;
    desc.mBytesPerLine = bytesPerLine;
}

ImageDesc::ImageDesc() : ForEachDesc(1,0) {} // SPU only

ImageDesc::ImageRegionDesc const & ImageDesc::GetImageRegionDesc(size_t number) const
{
    EA_ASSERT(number < sMaxImageRegionDescs);
    return mImageRegion[number];
}

size_t ImageDesc::GetOffsetForRegion(size_t number, int index) const
{
    ImageRegionDesc const& imageRegionDesc = GetImageRegionDesc(number);

    size_t y = imageRegionDesc.mYOffset + (index / mRowStep) * mRegionHeight;
    size_t x = imageRegionDesc.mXOffset + (index % mRowStep) * mRegionWidth;

    return (y * imageRegionDesc.mBytesPerLine) + (x * imageRegionDesc.mBytesPerPixel);
}

size_t ImageDesc::GetXOffsetForRegion(size_t number, int index) const
{
    ImageRegionDesc const& imageRegionDesc = GetImageRegionDesc(number);

    return imageRegionDesc.mXOffset + (index % mRowStep) * mRegionWidth;
}

size_t ImageDesc::GetYOffsetForRegion(size_t number, int index) const
{
    ImageRegionDesc const& imageRegionDesc = GetImageRegionDesc(number);

    return imageRegionDesc.mYOffset + (index / mRowStep) * mRegionHeight;
}

bool ImageDesc::Verify() const
{
    return ForEachDesc::Verify(sizeof(ImageDesc), sImageRegionDescIdent);
}


}}