413 lines
10 KiB
C++
413 lines
10 KiB
C++
/**********************************************************************
|
|
|
|
Filename : GImageInfo.h
|
|
Content : Image resource representation for GFxPlayer
|
|
Created : January 30, 2007
|
|
Authors : Michael Antonov
|
|
|
|
Notes :
|
|
|
|
Copyright : (c) 2005-2006 Scaleform Corp. All Rights Reserved.
|
|
|
|
Licensees may use this file in accordance with the valid Scaleform
|
|
Commercial License Agreement provided with the software.
|
|
|
|
This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
|
|
THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR ANY PURPOSE.
|
|
|
|
**********************************************************************/
|
|
|
|
#include "GImageInfo.h"
|
|
#include "GImage.h"
|
|
#include "GHeapNew.h"
|
|
|
|
|
|
// ***** GFxImageInfoBase
|
|
|
|
GImageInfoBase* GImageInfoBase::CreateSubImage(const GRect<SInt>& rect,
|
|
GMemoryHeap* pheap)
|
|
{
|
|
return GHEAP_NEW(pheap) GSubImageInfo(this, rect);
|
|
}
|
|
|
|
|
|
// ***** GFxImageInfoBaseImpl implementation
|
|
|
|
GImageInfoBaseImpl::GImageInfoBaseImpl(GTexture *ptexture)
|
|
: pTexture(ptexture)
|
|
{
|
|
if (ptexture)
|
|
ptexture->AddChangeHandler(this);
|
|
TextureUsage = GTexture::Usage_Wrap;
|
|
}
|
|
|
|
GImageInfoBaseImpl::~GImageInfoBaseImpl()
|
|
{
|
|
if (pTexture)
|
|
pTexture->RemoveChangeHandler(this);
|
|
}
|
|
|
|
GTexture* GImageInfoBaseImpl::GetTexture(GRenderer* prenderer)
|
|
{
|
|
if (pTexture)
|
|
{
|
|
// We currently only support one renderer
|
|
GASSERT(pTexture->GetRenderer() == prenderer);
|
|
return pTexture;
|
|
}
|
|
|
|
pTexture = *prenderer->CreateTexture();
|
|
if (pTexture)
|
|
{
|
|
// Use our function to override the texture.
|
|
if (Recreate(prenderer))
|
|
pTexture->AddChangeHandler(this);
|
|
else
|
|
pTexture = 0;
|
|
}
|
|
return pTexture.GetPtr();
|
|
}
|
|
|
|
|
|
// GTexture::ChangeHandler implementation
|
|
void GImageInfoBaseImpl::OnChange(GRenderer* prenderer, EventType changeType)
|
|
{
|
|
GUNUSED(prenderer);
|
|
|
|
// Currently we just handle renderer death by destroying its textures
|
|
// Texture Data loss does not need to be handled because Recreate will
|
|
// restore the image data if possible. For RT textures we handle it separately.
|
|
if (pTexture)
|
|
{
|
|
if (changeType == Event_RendererReleased)
|
|
{
|
|
pTexture->RemoveChangeHandler(this);
|
|
pTexture = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// ***** GImageInfo implementation
|
|
|
|
GImageInfo::GImageInfo(GImage *pimage, bool releaseImage)
|
|
: pImage(pimage), TargetWidth(0), TargetHeight(0), ReleaseImage(releaseImage)
|
|
{
|
|
TextureUsage = GTexture::Usage_Wrap;
|
|
|
|
#ifdef GFX_AMP_SERVER
|
|
ImageId = GetNextImageId();
|
|
#endif
|
|
}
|
|
|
|
GImageInfo::GImageInfo(GImage *pimage, UInt targetWidth, UInt targetHeight, bool releaseImage)
|
|
: pImage(pimage), TargetWidth(targetWidth), TargetHeight(targetHeight),
|
|
ReleaseImage(releaseImage)
|
|
{
|
|
TextureUsage = GTexture::Usage_Wrap;
|
|
|
|
#ifdef GFX_AMP_SERVER
|
|
ImageId = GetNextImageId();
|
|
#endif
|
|
}
|
|
|
|
GImageInfo::GImageInfo(GTexture *ptexture, UInt targetWidth, UInt targetHeight)
|
|
: GImageInfoBaseImpl(ptexture), pImage(0),
|
|
TargetWidth(targetWidth), TargetHeight(targetHeight), ReleaseImage(false)
|
|
{
|
|
// Note: GImageInfoBaseImpl will install a texture handler on us.
|
|
|
|
#ifdef GFX_AMP_SERVER
|
|
ImageId = GetNextImageId();
|
|
#endif
|
|
}
|
|
|
|
GImageInfo::~GImageInfo()
|
|
{
|
|
// pTexture handler is removed in ~GImageInfoBaseImpl.
|
|
}
|
|
|
|
#ifdef GFX_AMP_SERVER
|
|
UInt32 GImageInfoBase::GetNextImageId()
|
|
{
|
|
static GLock staticLock;
|
|
static UInt32 nextImageId = 0;
|
|
|
|
GLock::Locker locker(&staticLock);
|
|
return (++nextImageId);
|
|
}
|
|
#endif // GFX_AMP_SERVER
|
|
|
|
|
|
// MA - Notes for future:
|
|
//
|
|
// GetWidth() / GetHeight() prefer {TargetWidth, TargetHeight} over the dimensions
|
|
// of the image to ensure proper scaling in case of RenderTexture substitution.
|
|
// Technically {TargetWidth, TargetHeight} would not be needed in any other
|
|
// cases, except that there is no way to obtain them from texture.
|
|
// So, in the future if we add GTexture::GetWidth() a more appropriate logic
|
|
// would be:
|
|
// return TargetWidth ? TargetWidth :
|
|
// (pImage ? pImage->Width : (pTexture ? pTexture->GetWidth() : 0);
|
|
// In that situation we can stop passing {TargetWidth, TargetHeight} in the
|
|
// constructor and just have a special function GetSizeOverride()...
|
|
// Of course, we would also need to consider all the 'gfxexport' cases, such
|
|
// as padding of DDS textures, but that can be accounted for by the rectangle
|
|
// in GSubImageInfo.
|
|
|
|
UInt GImageInfo::GetWidth() const
|
|
{
|
|
return TargetWidth ? TargetWidth : (pImage ? pImage->Width : 0);
|
|
}
|
|
UInt GImageInfo::GetHeight() const
|
|
{
|
|
return TargetHeight ? TargetHeight : (pImage ? pImage->Height : 0);
|
|
}
|
|
|
|
#ifdef GFX_AMP_SERVER
|
|
|
|
UPInt GImageInfo::GetBytes() const
|
|
{
|
|
if (!pImage)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return pImage->Width * pImage->Height * pImage->GetBytesPerPixel();
|
|
}
|
|
|
|
bool GImageInfo::IsExternal() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
GImageBase::ImageFormat GImageInfo::GetFormat() const
|
|
{
|
|
if (!pImage)
|
|
{
|
|
return GImageBase::Image_None;
|
|
}
|
|
return pImage->Format;
|
|
}
|
|
|
|
|
|
#endif // GFX_AMP_SERVER
|
|
|
|
|
|
|
|
// *** Data Assignment
|
|
|
|
void GImageInfo::SetImage(GImage* pimage)
|
|
{
|
|
pImage = pimage;
|
|
if (pTexture)
|
|
Recreate(pTexture->GetRenderer());
|
|
}
|
|
void GImageInfo::SetImage(GImage* pimage, UInt targetWidth, UInt targetHeight)
|
|
{
|
|
TargetWidth = targetWidth;
|
|
TargetHeight = targetHeight;
|
|
SetImage(pimage);
|
|
}
|
|
|
|
// Sets the texture and potential target dimensions.
|
|
void GImageInfo::SetTexture(GTexture *ptexture)
|
|
{
|
|
if (pTexture == ptexture)
|
|
return;
|
|
// Clear image, if any.
|
|
pImage = 0;
|
|
if (pTexture)
|
|
pTexture->RemoveChangeHandler(this);
|
|
if (ptexture)
|
|
ptexture->AddChangeHandler(this);
|
|
pTexture = ptexture;
|
|
}
|
|
void GImageInfo::SetTexture(GTexture *ptexture, UInt targetWidth, UInt targetHeight)
|
|
{
|
|
TargetWidth = targetWidth;
|
|
TargetHeight = targetHeight;
|
|
SetTexture(ptexture);
|
|
}
|
|
|
|
void GImageInfo::SetTextureUsage(UInt usage)
|
|
{
|
|
if (!pImage)
|
|
{
|
|
GFC_DEBUG_WARNING(1, "No image, keeping existing texture");
|
|
return;
|
|
}
|
|
if (usage != 0 && usage != TextureUsage && pTexture)
|
|
{
|
|
pTexture->RemoveChangeHandler(this);
|
|
pTexture = 0;
|
|
}
|
|
TextureUsage = usage;
|
|
}
|
|
|
|
|
|
// Override GetTexture so that no attempt to create texture takes place if
|
|
// there is no backup image date for initialization.
|
|
GTexture* GImageInfo::GetTexture(GRenderer* prenderer)
|
|
{
|
|
if (pTexture)
|
|
{
|
|
// We currently only support one renderer
|
|
GASSERT(pTexture->GetRenderer() == prenderer);
|
|
return pTexture;
|
|
}
|
|
|
|
// If there is no image, no need to call Recreate on a texture
|
|
// since it can not possibly succeed.
|
|
if (!pImage)
|
|
return 0;
|
|
|
|
pTexture = *prenderer->CreateTexture();
|
|
if (pTexture)
|
|
{
|
|
// Use our function to override the texture.
|
|
if (Recreate(prenderer))
|
|
pTexture->AddChangeHandler(this);
|
|
else
|
|
pTexture = 0;
|
|
}
|
|
if (pTexture && ReleaseImage)
|
|
pImage = 0;
|
|
return pTexture.GetPtr();
|
|
}
|
|
|
|
|
|
// Override OnChange so that we can clear out pTexture pointer on data loss
|
|
// when there is no backup image. Users can override this behavior if desired.
|
|
void GImageInfo::OnChange(GRenderer* prenderer, EventType changeType)
|
|
{
|
|
GImageInfoBaseImpl::OnChange(prenderer, changeType);
|
|
|
|
// Unlike regular ImageInfo which can Recreate its data based on GImage,
|
|
// GImageInfo texture can not do so (instead it waits for the user to call
|
|
// SetTexture again). Until such call takes place we just handle data
|
|
// loss by releasing the texture object.
|
|
if (pTexture && (changeType == Event_DataLost) &&
|
|
(pImage.GetPtr() == 0) )
|
|
{
|
|
pTexture->RemoveChangeHandler(this);
|
|
pTexture = 0;
|
|
}
|
|
}
|
|
|
|
// Override recreate - to initialize texture data.
|
|
// We actually populate texture data from the image here.
|
|
bool GImageInfo::Recreate(GRenderer* prenderer)
|
|
{
|
|
GUNUSED(prenderer);
|
|
|
|
if (pTexture)
|
|
{
|
|
if (pImage)
|
|
{
|
|
if (pTexture->InitTexture(pImage, TextureUsage))
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
// This may happen if images were not loaded or bound by user correctly.
|
|
GFC_DEBUG_WARNING(1,
|
|
"GImageInfo::GetTexture failed, image not available. "
|
|
"Please check GFxLoader::LoadImageData flag.");
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
GImageInfoBase* GSubImageInfo::CreateSubImage(const GRect<SInt>& rect, GMemoryHeap* pheap)
|
|
{
|
|
GRect<SInt> subrect = rect;
|
|
subrect.Left += Rect.Left;
|
|
subrect.Top += Rect.Top;
|
|
return GHEAP_NEW(pheap) GSubImageInfo(this, subrect);
|
|
}
|
|
|
|
GSubImageInfo::GSubImageInfo(GImageInfoBase* pbase, GRect<SInt> rect)
|
|
: pBaseImage(pbase), Rect(rect)
|
|
{
|
|
#ifdef GFX_AMP_SERVER
|
|
ImageId = GetNextImageId();
|
|
#endif
|
|
|
|
}
|
|
|
|
/*
|
|
///////////////////////////////
|
|
GImageFileInfo::~GImageFileInfo()
|
|
{
|
|
if (pFileName) GFREE(pFileName);
|
|
}
|
|
|
|
void GImageFileInfo::SetFileName(const char* name)
|
|
{
|
|
if (pFileName)
|
|
GFREE((void*)pFileName);
|
|
|
|
char* ptr = 0;
|
|
if (name)
|
|
{
|
|
int len = int(strlen(name));
|
|
ptr = (char*)GALLOC(len + 1);
|
|
memcpy(ptr, name, len+1);
|
|
}
|
|
pFileName = ptr;
|
|
}
|
|
|
|
GTexture* GImageFileInfo::GetTexture(class GRenderer* prenderer)
|
|
{
|
|
if (pTexture)
|
|
{
|
|
// We currently only support one renderer
|
|
GASSERT(pTexture->GetRenderer() == prenderer);
|
|
return pTexture;
|
|
}
|
|
|
|
if (pFileName)
|
|
{
|
|
if ((pTexture = *prenderer->CreateTextureFromFile(pFileName, TargetWidth, TargetHeight)))
|
|
{
|
|
pTexture->AddChangeHandler(this);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This may happen if images were not loaded or bound by user correctly.
|
|
GFC_DEBUG_WARNING(1, "GImageFileInfo::GetTexture failed, image not available. Please check GFxLoader::LoadImageData flag.");
|
|
}
|
|
return pTexture;
|
|
|
|
}
|
|
|
|
// GTexture::ChangeHandler implementation
|
|
void GImageFileInfo::OnChange(GRenderer* prenderer, EventType changeType)
|
|
{
|
|
GUNUSED(prenderer);
|
|
|
|
// Currently we just handle renderer death by destroying its textures
|
|
// Texture Data loss does not need to be handled because
|
|
if (pTexture)
|
|
{
|
|
if (changeType == Event_RendererReleased)
|
|
{
|
|
pTexture->RemoveChangeHandler(this);
|
|
pTexture = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool GImageFileInfo::Recreate(GRenderer* prenderer)
|
|
{
|
|
GUNUSED(prenderer);
|
|
|
|
if (pTexture && pFileName)
|
|
return pTexture->InitTextureFromFile(pFileName, TargetWidth, TargetHeight);
|
|
return 0;
|
|
}
|
|
*/
|