/* Copyright (c) 2009 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and/or associated documentation files (the
* "Materials"), to deal in the Materials without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Materials, and to
* permit persons to whom the Materials are furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/*! \ingroup wfc
* \file wfcimageprovider.c
*
* \brief SI image providers
*/
#include <stdio.h>
#include <stdlib.h>
#include "wfcimageprovider.h"
#include "wfcdevice.h"
#include "wfccontext.h"
#include "wfcstructs.h"
#include "owfimage.h"
#include "owfarray.h"
#include "owfmemory.h"
#include "owfobject.h"
#include "owfnativestream.h"
#include "owfdebug.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define FIRST_IMAGEPROVIDER_HANDLE 4000
static WFCint nextImageProviderHandle =
FIRST_IMAGEPROVIDER_HANDLE;
OWF_API_CALL void
WFC_IMAGE_PROVIDER_Ctor(void* self)
{
WFC_IMAGE_PROVIDER* ip;
ENTER(WFC_IMAGE_PROVIDER_Ctor);
ip = IMAGE_PROVIDER(self);
ip->lockedStream.image=NULL;
ip->lockedStream.lockCount=0;
LEAVE(WFC_IMAGE_PROVIDER_Dtor);
}
OWF_API_CALL void
WFC_IMAGE_PROVIDER_Dtor(void* self)
{
WFC_IMAGE_PROVIDER* ip;
ENTER(WFC_IMAGE_PROVIDER_Dtor);
ip = IMAGE_PROVIDER(self);
DPRINT(("ptr=%p, handle=%d", ip, ip->handle));
owfNativeStreamDestroy(ip->streamHandle);
DESTROY(ip->owner);
if (ip->lockedStream.image)
{
if (ip->lockedStream.lockCount)
{ /* belts and braces: unlock the read buffer when image provider is destroyed */
DPRINT(("Native stream buffer still locked when Image Provider destroyed ptr=%p, handle=%d", ip, ip->handle));
owfNativeStreamReleaseReadBuffer(ip->streamHandle, ip->lockedStream.buffer);
}
OWF_Image_Destroy(ip->lockedStream.image);
}
LEAVE(WFC_IMAGE_PROVIDER_Dtor);
}
static WFC_IMAGE_PROVIDER*
WFC_ImageProvider_DoCreate(void* owner, /*WFC_CONTEXT* context,*/
OWFNativeStreamType stream,
WFC_IMAGE_PROVIDER_TYPE type)
{
WFC_IMAGE_PROVIDER* object;
ENTER(WFC_ImageProvider_DoCreate);
if (!stream)
{
return NULL;
}
object = CREATE(WFC_IMAGE_PROVIDER);
if (!object)
{
return NULL;
}
owfNativeStreamAddReference(stream);
object->streamHandle = stream;
object->type = type;
object->contentUpdated = WFC_FALSE;
WFC_ImageProvider_LockForReading(object);
if (object->lockedStream.image==NULL || object->lockedStream.image->data==NULL)
{
owfNativeStreamDestroy(stream);
DESTROY(object);
return NULL;
}
WFC_ImageProvider_Unlock(object);
ADDREF(object->owner, owner);
LEAVE(WFC_ImageProvider_DoCreate);
return object;
}
OWF_API_CALL WFC_IMAGE_PROVIDER*
WFC_ImageProvider_Create(void* owner, /*WFC_CONTEXT* context,*/
OWFNativeStreamType stream,
WFC_IMAGE_PROVIDER_TYPE type)
{
WFC_IMAGE_PROVIDER* object;
ENTER(WFC_ImageProvider_Create);
object = WFC_ImageProvider_DoCreate(owner/*context*/, stream, type);
if (object)
{
object->handle = nextImageProviderHandle++;
DPRINT(("WFC_ImageProvider_Create: attaching image provider %d to "
"stream %p",
object->handle, object->streamHandle));
}
LEAVE(WFC_ImageProvider_Create);
return object;
}
OWF_API_CALL void
WFC_ImageProvider_LockForReading(WFC_IMAGE_PROVIDER* provider)
{
void* pixels;
OWFint width, height, pixelSize = 0;
OWF_IMAGE_FORMAT imgf;
OWFint stride;
if (!provider) {
DPRINT(("WFC_ImageProvider_LockForReading: provider = NULL"));
return;
}
OWF_ASSERT(provider->streamHandle);
DPRINT(("stream = %p", provider->streamHandle));
if (!provider->lockedStream.lockCount)
{
DPRINT(("About to acquire & lock a read buffer"));
/* acquire buffer */
provider->lockedStream.buffer = owfNativeStreamAcquireReadBuffer(provider->streamHandle);
DPRINT((" Acquired read buffer stream=%p, buffer=%d",
provider->streamHandle, provider->lockedStream.buffer));
/* Bind source image to pixel buffer */
pixels = owfNativeStreamGetBufferPtr(provider->streamHandle, provider->lockedStream.buffer);
if (provider->lockedStream.image)
{
OWF_Image_SetPixelBuffer(provider->lockedStream.image,pixels);
}
else
{
owfNativeStreamGetHeader(provider->streamHandle,
&width, &height,
&stride, &imgf, &pixelSize);
provider->lockedStream.image = OWF_Image_Create(width, height, &imgf, pixels, stride);
}
}
++provider->lockedStream.lockCount;
DPRINT(("lock count = %d", provider->lockedStream.lockCount));
}
OWF_API_CALL void
WFC_ImageProvider_Unlock(WFC_IMAGE_PROVIDER* provider)
{
if (!provider) {
DPRINT(("WFC_ImageProvider_Unlock: provider = NULL"));
return;
}
if (provider->lockedStream.lockCount > 0)
{
--provider->lockedStream.lockCount;
DPRINT(("lock count = %d", provider->lockedStream.lockCount));
if (!provider->lockedStream.lockCount)
{
DPRINT((" Releasing read buffer provider=%p, buffer=%d",
provider->handle, provider->lockedStream.buffer));
owfNativeStreamReleaseReadBuffer(provider->streamHandle, provider->lockedStream.buffer);
}
}
}
#ifdef __cplusplus
}
#endif