예제 #1
0
gceSTATUS vgfDereferenceObject(
	vgsCONTEXT_PTR Context,
	vgsOBJECT_PTR * Object
	)
{
	gceSTATUS status = gcvSTATUS_OK;

	gcmASSERT(Context != gcvNULL);
	gcmASSERT(Object != gcvNULL);

	do
	{
		/* Get a shortcut to the object. */
		vgsOBJECT_PTR object = *Object;

		/* Already destroyed? */
		if (object == gcvNULL)
		{
			break;
		}

		/* Valid reference count? */
		if (object->referenceCount < 1)
		{
			gcmFATAL("Invalid reference count found.");
			status = gcvSTATUS_INVALID_OBJECT;
			break;
		}

		/* Decrement the reference count. */
		object->referenceCount--;

		/* Time to destroy? */
		if (object->referenceCount == 0)
		{
			vgsOBJECT_LIST_PTR objectList;

			/* Get a shortcut to the object list. */
			objectList = &Context->objectCache->cache[object->type];

			/* Call the destructor. */
			gcmASSERT(objectList->destructor != gcvNULL);
			gcmERR_BREAK(objectList->destructor(Context, object));

			/* Remove the object from the cache. */
			gcmERR_BREAK(vgfObjectCacheRemove(Context, object));

			/* Free the object. */
			gcmERR_BREAK(gcoOS_Free(Context->os, object));

			/* Reset the pointer. */
			*Object = gcvNULL;
		}
	}
	while (gcvFALSE);

	/* Return status. */
	return status;
}
예제 #2
0
/*******************************************************************************
**
**  gcoDUMP_DumpData
**
**  Dump data the file.
**
**  INPUT:
**
**      gcoDUMP Dump
**          Pointer to a gcoDUMP object.
**
**      gceDUMP_TAG Type
**          Type of data.
**
**      gctUINT32 Address
**          Physical address to be used as a handle for the data.
**
**      gctSIZE_T ByteCount
**          Number of bytes to write.
**
**      gctCONST_POINTER Data
**          Pointer to the data to write.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_DumpData(
    IN gcoDUMP Dump,
    IN gceDUMP_TAG Type,
    IN gctUINT32 Address,
    IN gctSIZE_T ByteCount,
    IN gctCONST_POINTER Data
    )
{
    gceSTATUS status;
    gcsDUMP_DATA header;

    gcmHEADER_ARG("Dump=0x%x Type=%d Address=%x ByteCount=%d Data=0x%x",
                    Dump, Type, Address, ByteCount, Data);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP);
    gcmVERIFY_ARGUMENT(ByteCount > 0);
    gcmVERIFY_ARGUMENT(Data != gcvNULL);

    if (Dump->file == gcvNULL)
    {
        /* There is no open dump file. */
        gcmFOOTER_NO();
        return gcvSTATUS_OK;
    }

    do
    {
        /* Write the data record. */
        header.type    = Type;
        header.length  = ByteCount;
        header.address = Address;

        gcmERR_BREAK(
            gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header));

        /* Write the data. */
        gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, ByteCount, Data));

        /* Update the frame length. */
        Dump->frameLength += sizeof(header) + ByteCount;

        /* Update the file length. */
        Dump->length += sizeof(header) + ByteCount;
    }
    while (gcvFALSE);

    /* Return the status. */
    gcmFOOTER();
    return status;
}
예제 #3
0
/*******************************************************************************
**
**  gcoDUMP_FrameEnd
**
**  Mark the end of a frame.
**
**  INPUT:
**
**      gcoDUMP Dump
**          Pointer to a gcoDUMP object.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_FrameEnd(
    IN gcoDUMP Dump
    )
{
    gceSTATUS status;
    gcsDUMP_DATA header;
    gctUINT32 pos;

    gcmHEADER_ARG("Dump=0x%x", Dump);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP);

    if (Dump->file == gcvNULL)
    {
        /* There is no open dump file. */
        gcmFOOTER_NO();
        return gcvSTATUS_OK;
    }

    do
    {
        /* Get the current position. */
        gcmERR_BREAK(gcoOS_GetPos(gcvNULL, Dump->file, &pos));

        /* Seek to the beginning of the frame. */
        gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, Dump->frameStart));

        /* Make sure we got the right byte count. */
        gcmASSERT(pos - Dump->frameStart == Dump->frameLength + sizeof(header));

        /* Update the frame header. */
        header.type    = gcvTAG_FRAME;
        header.length  = Dump->frameLength;
        header.address = ++ Dump->frameCount;

        gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header));

        /* Seek to the end of the file. */
        gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, pos));

        /* Mark the frame as ended. */
        Dump->frameStart = 0;
    }
    while (gcvFALSE);

    /* Return the status. */
    gcmFOOTER();
    return status;
}
예제 #4
0
static gceSTATUS _CLOSE_PATH(
	vgsPATHWALKER_PTR Destination
	)
{
	gceSTATUS status;
	vgsCONTROL_COORD_PTR coords;

	do
	{
		/* Get a shortcut to the control coordinates. */
		coords = Destination->coords;

		/* Add new command. */
		gcmERR_BREAK(vgsPATHWALKER_WriteCommand(
			Destination, gcvVGCMD_CLOSE
			));

		/* Update the control coordinates. */
		coords->lastX    = coords->startX;
		coords->lastY    = coords->startY;
		coords->controlX = coords->startX;
		coords->controlY = coords->startY;

		/* Success. */
		return gcvSTATUS_OK;
	}
	while (gcvFALSE);

	/* Return status. */
	return status;
}
gceSTATUS vgsMEMORYMANAGER_Construct(
    IN gcoOS Os,
	IN gctUINT ItemSize,
	IN gctUINT Granularity,
	OUT vgsMEMORYMANAGER_PTR * Manager
	)
{
	gceSTATUS status;
	vgsMEMORYMANAGER_PTR manager = gcvNULL;

    gcmHEADER_ARG("Os=0x%x ItemSize=0x%x Granularity=0x%x Manager=0x%x",
        Os, ItemSize, Granularity, Manager);

	gcmVERIFY_ARGUMENT(ItemSize > 0);
	gcmVERIFY_ARGUMENT(Granularity > 0);
	gcmVERIFY_ARGUMENT(Manager != gcvNULL);

	do
	{
		gctUINT itemSize;
		gctUINT allocationSize;

		/* Allocate the memory manager structure. */
		gcmERR_BREAK(gcoOS_Allocate(
			Os,
			gcmSIZEOF(vgsMEMORYMANAGER),
			(gctPOINTER *) &manager
			));

		/* Determine the size of the item. */
		itemSize = gcmSIZEOF(vgsMEMORYITEM) + ItemSize;

		/* Determine the allocation size. */
		allocationSize = gcmSIZEOF(vgsMEMORYITEM) + Granularity * itemSize;

		/* Initialize the structure. */
		manager->os             = Os;
		manager->allocationSize = allocationSize;
		manager->itemCount      = Granularity;
		manager->itemSize       = itemSize;
		manager->firstAllocated = gcvNULL;
		manager->firstFree      = gcvNULL;

#if vgvVALIDATE_MEMORY_MANAGER
		manager->allocatedCount       = 0;
		manager->maximumAllocated     = 0;
		manager->allocatedBufferCount = 0;
#endif

		/* Set the result pointer. */
		* Manager = manager;
	}
	while (gcvNULL);

    gcmFOOTER();

	/* Return status. */
	return status;
}
예제 #6
0
static gceSTATUS _SMALL_ARC(
	vgsPATHWALKER_PTR Destination,
	gctBOOL CounterClockwise,
	gctBOOL Relative,
	gctFLOAT HorRadius,
	gctFLOAT VerRadius,
	gctFLOAT RotAngle,
	gctFLOAT EndX,
	gctFLOAT EndY
	)
{
	gceSTATUS status;
	vgsPATHWALKER arc;
	vgsCONTEXT_PTR context;

	do
	{
		/* Close the current subpath. */
		vgsPATHWALKER_CloseSubpath(Destination);

		/* Get a shortcut to the context. */
		context = Destination->context;

		/* Prepare for writing the destination. */
		vgsPATHWALKER_InitializeWriter(
			context, context->pathStorage, &arc, Destination->path
			);

		/* Generate the ARC buffer. */
		gcmERR_BREAK(vgfConvertArc(
			&arc,
			HorRadius, VerRadius,
			RotAngle,
			EndX, EndY,
			CounterClockwise,
			gcvFALSE,
			Relative
			));

		/* Append to the existing buffer. */
		vgsPATHWALKER_AppendData(
			Destination, &arc, 1, 5
			);

		/* Set the ARC present flag. */
		Destination->path->hasArcs = gcvTRUE;

		/* Success. */
		return gcvSTATUS_OK;
	}
	while (gcvFALSE);

	/* Return status. */
	return status;
}
예제 #7
0
static gceSTATUS _CreateBuffer(
    IN glsCONTEXT_PTR Context,
    IN gctUINT32 Buffer,
    OUT glsNAMEDOBJECT_PTR * Wrapper
    )
{
    gceSTATUS status;

    gcmHEADER_ARG("Context=0x%x Buffer=%u Wrapper=0x%x",
                  Context, Buffer, Wrapper);

    do
    {
        glsBUFFER_PTR object;
        glsCONTEXT_PTR shared;

        /* Map shared context. */
#if gcdRENDER_THREADS
        shared = (Context->shared != gcvNULL) ? Context->shared : Context;
#else
        shared = Context;
#endif

        /* Attempt to allocate a new buffer. */
        gcmERR_BREAK(glfCreateNamedObject(
            Context,
            &shared->bufferList,
            Buffer,
            _DeleteBuffer,
            Wrapper
            ));

        /* Get a pointer to the new buffer. */
        object = (glsBUFFER_PTR) (*Wrapper)->object;

        /* Init the buffer to the defaults. */
        gcoOS_ZeroMemory(object, sizeof(glsBUFFER));
        object->usage = GL_STATIC_DRAW;
        object->mapped = gcvFALSE;
        object->bufferMapPointer = gcvNULL;

#if gcdUSE_TRIANGLE_STRIP_PATCH
        object->stripPatchDirty = gcvTRUE;
        object->subCount        = 0;

        gcoOS_ZeroMemory(object->subs, sizeof(object->subs));
#endif
    }
    while (gcvFALSE);

    gcmFOOTER();

    /* Return result. */
    return status;
}
예제 #8
0
/*******************************************************************************
**
**  gcoDUMP_FrameBegin
**
**  Mark the beginning of a frame.
**
**  INPUT:
**
**      gcoDUMP Dump
**          Pointer to a gcoDUMP object.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_FrameBegin(
    IN gcoDUMP Dump
    )
{
    gceSTATUS status;
    gcsDUMP_DATA header;

    gcmHEADER_ARG("Dump=0x%x", Dump);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP);

    if ( (Dump->file == gcvNULL) || (Dump->frameStart != 0) )
    {
        /* There is no open dump file. */
        gcmFOOTER_NO();
        return gcvSTATUS_OK;
    }

    do
    {
        /* Get the current position. */
        gcmERR_BREAK(gcoOS_GetPos(gcvNULL, Dump->file, &Dump->frameStart));

        /* Write the frame header. */
        header.type    = gcvTAG_FRAME;
        header.length  = Dump->frameLength = 0;
        header.address = 0;

        gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header));

        /* Update the file length. */
        Dump->length += sizeof(header);
    }
    while (gcvFALSE);

    /* Return the status. */
    gcmFOOTER();
    return status;
}
예제 #9
0
/*******************************************************************************
**
**  gcoDUMP_AddSurface
**
**  Allocate a surface.
**
**  INPUT:
**
**      gcoDUMP Dump
**          Pointer to a gcoDUMP object.
**
**      gctINT32 Width, Height
**          Width and height of the surface.
**
**      gceSURF_FORMAT PixelFormat
**          Pixel format for the surface.
**
**      gctUINT32 Address
**          Physical address to be used as a handle for the surface.
**
**      gctSIZE_T ByteCount
**          Number of bytes inside the surface.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_AddSurface(
    IN gcoDUMP Dump,
    IN gctINT32 Width,
    IN gctINT32 Height,
    IN gceSURF_FORMAT PixelFormat,
    IN gctUINT32 Address,
    IN gctSIZE_T ByteCount
    )
{
    gceSTATUS status;
    gcsDUMP_SURFACE surface;

    gcmHEADER_ARG("Dump=0x%x Width=%d Height=%d PixelFormat=%d Address=%x "
                  "ByteCount=%d",
                  Dump, Width, Height, PixelFormat, Address, ByteCount);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP);
    gcmVERIFY_ARGUMENT(ByteCount > 0);

    if (Dump->file == gcvNULL)
    {
        /* There is no open dump file. */
        gcmFOOTER_NO();
        return gcvSTATUS_OK;
    }

    do
    {
        /* Write the data record. */
        surface.type    = gcvTAG_SURFACE;
        surface.address = Address;
        surface.width   = (gctINT16) Width;
        surface.height  = (gctINT16) Height;
        surface.format  = PixelFormat;
        surface.length  = ByteCount;

        gcmERR_BREAK(
            gcoOS_Write(gcvNULL, Dump->file, sizeof(surface), &surface));

        /* Update the frame length. */
        Dump->frameLength += sizeof(surface);

        /* Update the file length. */
        Dump->length += sizeof(surface);
    }
    while (gcvFALSE);

    /* Return the status. */
    gcmFOOTER();
    return status;
}
예제 #10
0
gceSTATUS
_FreeSurface(
    IN gcsSURFACE * Surface
    )
{
    gceSTATUS status = gcvSTATUS_OK;

    if (Surface == gcvNULL)
    {
        return gcvSTATUS_INVALID_ARGUMENT;
    }

    do
    {
        if (Surface->surface != gcvNULL)
        {
            if (Surface->logical != gcvNULL)
            {
                gcmERR_BREAK(
                    gcoSURF_Unlock(Surface->surface,
                                   Surface->logical));
            }

            gcmERR_BREAK(
                gcoSURF_Destroy(Surface->surface));

            Surface->surface  = gcvNULL;
            Surface->physical = ~0;
            Surface->logical  = gcvNULL;
            Surface->width    = 0;
            Surface->height   = 0;
            Surface->format   = gcvSURF_UNKNOWN;
        }
    }
    while (gcvFALSE);

    return status;
}
gceSTATUS vgsMEMORYMANAGER_Destroy(
	IN vgsMEMORYMANAGER_PTR Manager
	)
{
	gceSTATUS status;
	vgsMEMORYITEM_PTR current;
	vgsMEMORYITEM_PTR next;

    gcmHEADER_ARG("Manager=0x%x", Manager);

	/* Verify arguments. */
	gcmVERIFY_ARGUMENT(Manager != gcvNULL);

	/* Assume success. */
	status = gcvSTATUS_OK;

	/* Everything has to be freed. */
#if vgvVALIDATE_MEMORY_MANAGER
	gcmASSERT(Manager->allocatedCount == 0);
#endif

	/* Destroy all allocated buffers. */
	while (Manager->firstAllocated)
	{
		/* Get the current buffer. */
		current = Manager->firstAllocated;

		/* Get the next buffer. */
		next = current->next;

		/* Free the current. */
		gcmERR_BREAK(gcoOS_Free(Manager->os, current));

		/* Advance to the next one. */
		Manager->firstAllocated = next;
	}

	/* Success? */
	if (gcmIS_SUCCESS(status))
	{
		status = gcoOS_Free(Manager->os, Manager);
	}

    gcmFOOTER();
	/* Return status. */
	return status;
}
예제 #12
0
/*******************************************************************************
**
**  gcoDUMP_Delete
**
**  Mark an address as deleted.
**
**  INPUT:
**
**      gcoDUMP Dump
**          Pointer to a gcoDUMP object.
**
**      gctUINT32 Address
**          Physical address to delete.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_Delete(
    IN gcoDUMP Dump,
    IN gctUINT32 Address
    )
{
    gceSTATUS status;
    gcsDUMP_DATA header;

    gcmHEADER_ARG("Dump=0x%x Address=%x", Dump, Address);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP);

    if (Dump->file == gcvNULL)
    {
        /* There is no open dump file. */
        gcmFOOTER_NO();
        return gcvSTATUS_OK;
    }

    do
    {
        /* Write the delete record. */
        header.type    = gcvTAG_DELETE;
        header.length  = 0;
        header.address = Address;

        gcmERR_BREAK(
            gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header));

        /* Update the frame length. */
        Dump->frameLength += sizeof(header);

        /* Update the file length. */
        Dump->length += sizeof(header);
    }
    while (gcvFALSE);

    /* Return the status. */
    gcmFOOTER();
    return status;
}
예제 #13
0
static gceSTATUS _MOVE_TO_ABS(
	vgsPATHWALKER_PTR Destination,
	gctFLOAT X,
	gctFLOAT Y
	)
{
	gceSTATUS status;
	vgsCONTROL_COORD_PTR coords;

	do
	{
		/* Get a shortcut to the control coordinates. */
		coords = Destination->coords;

		/* Add new command. */
		gcmERR_BREAK(vgsPATHWALKER_WriteCommand(
			Destination, gcvVGCMD_MOVE
			));

		/* Set the command coordinates. */
		Destination->set(Destination, X);
		Destination->set(Destination, Y);

		/* Update the control coordinates. */
		coords->startX   = X;
		coords->startY   = Y;
		coords->lastX    = X;
		coords->lastY    = Y;
		coords->controlX = X;
		coords->controlY = Y;

		/* Success. */
		return gcvSTATUS_OK;
	}
	while (gcvFALSE);

	/* Return status. */
	return status;
}
예제 #14
0
static gceSTATUS _VLINE_TO_REL(
	vgsPATHWALKER_PTR Destination,
	gctFLOAT Y
	)
{
	gceSTATUS status;
	gctFLOAT absY;
	vgsCONTROL_COORD_PTR coords;

	do
	{
		/* Get a shortcut to the control coordinates. */
		coords = Destination->coords;

		/* Add new command. */
		gcmERR_BREAK(vgsPATHWALKER_WriteCommand(
			Destination, gcvVGCMD_VLINE_EMUL_REL
			));

		/* Set the command coordinates. */
		Destination->set(Destination, 0.0f);
		Destination->set(Destination, Y);

		/* Determine the absolute coordinate. */
		absY = Y + coords->lastY;

		/* Update the control coordinates. */
		coords->lastY    = absY;
		coords->controlX = coords->lastX;
		coords->controlY = absY;

		/* Success. */
		return gcvSTATUS_OK;
	}
	while (gcvFALSE);

	/* Return status. */
	return status;
}
예제 #15
0
/*******************************************************************************
**
**  gcoDUMP_Construct
**
**  Construct a new gcoDUMP object.
**
**  INPUT:
**
**      gcoOS Os
**          Pointer to an gcoOS object.
**
**      gcoOS Hal
**          Pointer to an gcoHAL object.
**
**  OUTPUT:
**
**      gcoDUMP * Dump
**          Pointer to a variable receiving the gcoDUMP object pointer.
*/
gceSTATUS
gcoDUMP_Construct(
    IN gcoOS Os,
    IN gcoHAL Hal,
    OUT gcoDUMP * Dump
    )
{
    gceSTATUS status;
    gcoDUMP dump;
    gctPOINTER pointer = gcvNULL;

    gcmHEADER_ARG("Os=0x%x Dump=0x%x", Os, Dump);

    /* Verify the arguments. */
    gcmVERIFY_ARGUMENT(Dump != gcvNULL);

    do
    {
        /* Allocate the gcoDUMP structure. */
        gcmERR_BREAK(gcoOS_Allocate(Os,
                                    sizeof(struct _gcoDUMP),
                                    &pointer));

        dump = pointer;

        /* Initialize the gcoDUMP object. */
        dump->object.type = gcvOBJ_DUMP;
        dump->file        = gcvNULL;

        /* Return pointer to the object. */
        *Dump = dump;
    }
    while (gcvFALSE);

    /* Return the status. */
    gcmFOOTER_ARG("*Dump=0x%x", *Dump);
    return status;
}
예제 #16
0
gceSTATUS vgfConvertArc(
	vgsPATHWALKER_PTR Destination,
	gctFLOAT HorRadius,
	gctFLOAT VerRadius,
	gctFLOAT RotAngle,
	gctFLOAT EndX,
	gctFLOAT EndY,
	gctBOOL CounterClockwise,
	gctBOOL Large,
	gctBOOL Relative
	)
{
	gceSTATUS status;
	vgsARCCOORDINATES_PTR arcCoords = gcvNULL;

	do
	{
		gctFLOAT endX, endY;
		gceVGCMD segmentCommand;
		vgsCONTROL_COORD_PTR coords;


		/*******************************************************************
		** Determine the absolute end point coordinates.
		*/

		/* Get a shortcut to the control coordinates. */
		coords = Destination->coords;

		if (Relative)
		{
			endX = EndX + coords->lastX;
			endY = EndY + coords->lastY;
		}
		else
		{
			endX = EndX;
			endY = EndY;
		}

		/* If both of the radiuses are zeros, make a line out of the arc. */
		if ((HorRadius == 0.0f) || (VerRadius == 0.0f) ||
			((endX == coords->lastX) && (endY == coords->lastY)))
		{
			/* Determine the segment command. */
			segmentCommand = Relative
				? gcvVGCMD_ARC_LINE_REL
				: gcvVGCMD_ARC_LINE;

			/* Allocate a new subpath. */
			gcmERR_BREAK(vgsPATHWALKER_StartSubpath(
				Destination, vgmCOMMANDSIZE(2, gctFLOAT), gcePATHTYPE_FLOAT
				));

			/* Write the command. */
			gcmERR_BREAK(vgsPATHWALKER_WriteCommand(
				Destination,
				segmentCommand
				));

			/* Write the coordinates. */
			Destination->set(Destination, EndX);
			Destination->set(Destination, EndY);
		}
		else
		{
			VGfloat phi, cosPhi, sinPhi;
			VGfloat dxHalf, dyHalf;
			VGfloat x1Prime, y1Prime;
			VGfloat rx, ry;
			VGfloat x1PrimeSquare, y1PrimeSquare;
			VGfloat lambda;
			VGfloat rxSquare, rySquare;
			VGint sign;
			VGfloat sq, signedSq;
			VGfloat cxPrime, cyPrime;
			VGfloat theta1, thetaSpan;
			VGint segs;
			VGfloat theta, ax, ay, x, y;
			VGfloat controlX, controlY, anchorX, anchorY;
			VGfloat lastX, lastY;
			gctUINT bufferSize;


			/*******************************************************************
			** Converting.
			*/

			phi = RotAngle / 180.0f * vgvPI;
			cosPhi = gcmCOSF(phi);
			sinPhi = gcmSINF(phi);

			if (Relative)
			{
				dxHalf = - EndX / 2.0f;
				dyHalf = - EndY / 2.0f;
			}
			else
			{
				dxHalf = (coords->lastX - endX) / 2.0f;
				dyHalf = (coords->lastY - endY) / 2.0f;
			}

			x1Prime =  cosPhi * dxHalf + sinPhi * dyHalf;
			y1Prime = -sinPhi * dxHalf + cosPhi * dyHalf;

			rx = gcmFABSF(HorRadius);
			ry = gcmFABSF(VerRadius);

			x1PrimeSquare = x1Prime * x1Prime;
			y1PrimeSquare = y1Prime * y1Prime;

			lambda = x1PrimeSquare / (rx * rx) + y1PrimeSquare / (ry * ry);
			if (lambda > 1.0f)
			{
				rx *= gcmSQRTF(lambda);
				ry *= gcmSQRTF(lambda);
			}

			rxSquare = rx * rx;
			rySquare = ry * ry;

			sign     = (Large == CounterClockwise) ? -1 : 1;
			sq       = ( rxSquare * rySquare
					   - rxSquare * y1PrimeSquare
					   - rySquare * x1PrimeSquare
					   )
					   /
					   ( rxSquare * y1PrimeSquare
					   + rySquare * x1PrimeSquare
					   );
			signedSq = sign * ((sq < 0) ? 0 : gcmSQRTF(sq));
			cxPrime  = signedSq *  (rx * y1Prime / ry);
			cyPrime  = signedSq * -(ry * x1Prime / rx);

			theta1 = _Angle(1, 0, (x1Prime - cxPrime) / rx, (y1Prime - cyPrime) / ry);
			theta1 = gcmFMODF(theta1, 2 * vgvPI);

			thetaSpan = _Angle(( x1Prime - cxPrime) / rx, ( y1Prime - cyPrime) / ry,
							   (-x1Prime - cxPrime) / rx, (-y1Prime - cyPrime) / ry);

			if (!CounterClockwise && (thetaSpan > 0))
			{
				thetaSpan -= 2 * vgvPI;
			}
			else if (CounterClockwise && (thetaSpan < 0))
			{
				thetaSpan += 2 * vgvPI;
			}

			thetaSpan = gcmFMODF(thetaSpan, 2 * vgvPI);


			/*******************************************************************
			** Drawing.
			*/

			segs  = (VGint) (gcmCEILF(gcmFABSF(thetaSpan) / (45.0f / 180.0f * vgvPI)));
			gcmASSERT(segs > 0);

			theta = thetaSpan / segs;

			ax = coords->lastX - gcmCOSF(theta1) * rx;
			ay = coords->lastY - gcmSINF(theta1) * ry;

			/* Determine the segment command. */
			segmentCommand = Relative
				? gcvVGCMD_ARC_QUAD_REL
				: gcvVGCMD_ARC_QUAD;

			/* Determine the size of the buffer required. */
			bufferSize = (1 + 2 * 2) * gcmSIZEOF(gctFLOAT) * segs;

			/* Allocate a new subpath. */
			gcmERR_BREAK(vgsPATHWALKER_StartSubpath(
				Destination, bufferSize, gcePATHTYPE_FLOAT
				));

			/* Set initial last point. */
			lastX = coords->lastX;
			lastY = coords->lastY;

			while (segs-- > 0)
			{
				theta1 += theta;

				controlX = ax + gcmCOSF(theta1 - (theta / 2.0f)) * rx / gcmCOSF(theta / 2.0f);
				controlY = ay + gcmSINF(theta1 - (theta / 2.0f)) * ry / gcmCOSF(theta / 2.0f);

				anchorX = ax + gcmCOSF(theta1) * rx;
				anchorY = ay + gcmSINF(theta1) * ry;

				if (RotAngle != 0)
				{
					x = coords->lastX + cosPhi * (controlX - coords->lastX) - sinPhi * (controlY - coords->lastY);
					y = coords->lastY + sinPhi * (controlX - coords->lastX) + cosPhi * (controlY - coords->lastY);
					controlX = x;
					controlY = y;

					x = coords->lastX + cosPhi * (anchorX - coords->lastX) - sinPhi * (anchorY - coords->lastY);
					y = coords->lastY + sinPhi * (anchorX - coords->lastX) + cosPhi * (anchorY - coords->lastY);
					anchorX = x;
					anchorY = y;
				}

				if (segs == 0)
				{
					/* Use end point directly to avoid accumulated errors. */
					anchorX = endX;
					anchorY = endY;
				}

				/* Adjust relative coordinates. */
				if (Relative)
				{
					VGfloat nextLastX = anchorX;
					VGfloat nextLastY = anchorY;

					controlX -= lastX;
					controlY -= lastY;

					anchorX -= lastX;
					anchorY -= lastY;

					lastX = nextLastX;
					lastY = nextLastY;
				}

				/* Write the command. */
				gcmERR_BREAK(vgsPATHWALKER_WriteCommand(
					Destination, segmentCommand
					));

				/* Set the coordinates. */
				Destination->set(Destination, controlX);
				Destination->set(Destination, controlY);
				Destination->set(Destination, anchorX);
				Destination->set(Destination, anchorY);
			}
		}

		/* Store ARC coordinates. */
		gcmERR_BREAK(vgsMEMORYMANAGER_Allocate(
			Destination->arcCoordinates,
			(gctPOINTER *) &arcCoords
			));

		arcCoords->large            = Large;
		arcCoords->counterClockwise = CounterClockwise;
		arcCoords->horRadius        = HorRadius;
		arcCoords->verRadius        = VerRadius;
		arcCoords->rotAngle         = RotAngle;
		arcCoords->endX             = EndX;
		arcCoords->endY             = EndY;

		/* Store the pointer to ARC coordinates. */
		Destination->currPathData->extraManager = Destination->arcCoordinates;
		Destination->currPathData->extra        = arcCoords;

		/* Update the control coordinates. */
		coords->lastX    = endX;
		coords->lastY    = endY;
		coords->controlX = endX;
		coords->controlY = endY;

		/* Success. */
		return gcvSTATUS_OK;
	}
	while (gcvFALSE);

	/* Roll back. */
	vgsPATHWALKER_Rollback(Destination);

	/* Return status. */
	return status;
}
gceSTATUS vgsMEMORYMANAGER_Allocate(
	IN vgsMEMORYMANAGER_PTR Manager,
	OUT gctPOINTER * Pointer
	)
{
	gceSTATUS status;
	vgsMEMORYITEM_PTR firstFree;

    gcmHEADER_ARG("Manager=0x%x Pointer=0x%x", Manager, Pointer);
	/* Verify arguments. */
	gcmVERIFY_ARGUMENT(Manager != gcvNULL);
	gcmVERIFY_ARGUMENT(Pointer != gcvNULL);

	/* Get the first free. */
	firstFree = Manager->firstFree;

	/* Are there free items? */
	if (firstFree != gcvNULL)
	{
		/* Set the result. */
		* Pointer = firstFree + 1;

		/* Remove from the free list. */
		Manager->firstFree = firstFree->next;

		/* Update allocated items count. */
#if vgvVALIDATE_MEMORY_MANAGER
		Manager->allocatedCount += 1;

		if ((gctUINT) Manager->allocatedCount > Manager->maximumAllocated)
		{
			Manager->maximumAllocated = Manager->allocatedCount;
		}
#endif

		/* Success. */
                gcmFOOTER_ARG("*Pointer=0x%x", *Pointer);
		return gcvSTATUS_OK;
	}

	/* No free items available. */
	do
	{
		vgsMEMORYITEM_PTR newBuffer;
		gctUINT i, itemCount;
		gctUINT itemSize;

		/* Allocate a new buffer. */
		gcmERR_BREAK(gcoOS_Allocate(
			Manager->os,
			Manager->allocationSize,
			(gctPOINTER) &newBuffer
			));

		/* Link in. */
		newBuffer->next = Manager->firstAllocated;
		Manager->firstAllocated = newBuffer;

		/* Set the result. */
		* Pointer = newBuffer + 2;

		/* Update allocated items count. */
#if vgvVALIDATE_MEMORY_MANAGER
		Manager->allocatedCount       += 1;
		Manager->allocatedBufferCount += 1;

		if ((gctUINT) Manager->allocatedCount > Manager->maximumAllocated)
		{
			Manager->maximumAllocated = Manager->allocatedCount;
		}
#endif

		/* Get the number of items per allocation. */
		itemCount = Manager->itemCount;

		/* Get the item size. */
		itemSize = Manager->itemSize;

		/* Determine the first free item. */
		firstFree = (vgsMEMORYITEM_PTR)
		(
			(gctUINT8_PTR) (newBuffer + 1) + itemSize
		);

		/* Populate the new buffer. */
		for (i = 1; i < itemCount; i++)
		{
			/* Add to the free item list. */
			firstFree->next = Manager->firstFree;
			Manager->firstFree = firstFree;

			/* Advance to the next item. */
			firstFree = (vgsMEMORYITEM_PTR)
			(
				(gctUINT8_PTR) firstFree + itemSize
			);
		}
	}
	while (gcvFALSE);

    gcmFOOTER();
	/* Return status. */
	return status;
}
예제 #18
0
/*******************************************************************************
**
**  _WorkaroundForFilterBlit
**
**  Workaround for the dirty region issue of filter blit.
**  It only exists for old GC300 before 2.0.2 (included).
**
**  INPUT:
**
**      gctHAL Hal
**          Pointer to HAL.
**
**  OUTPUT:
**
**      Nothing.
*/
static gceSTATUS
_WorkaroundForFilterBlit(
    IN gcoHAL Hal
    )
{
    gceSTATUS status;

    gcoSURF    srcSurf = gcvNULL;
    gcsRECT    srcRect;

    gcoSURF    dstSurf = gcvNULL;
    gcsRECT    dstRect;

    do
    {
        gcmERR_BREAK(gcoSURF_Construct(
            gcvNULL,
            256,
            256,
            1,
            gcvSURF_BITMAP,
            gcvSURF_A8R8G8B8,
            gcvPOOL_DEFAULT,
            &srcSurf
            ));

        gcmERR_BREAK(gcoSURF_Construct(
            gcvNULL,
            256,
            256,
            1,
            gcvSURF_BITMAP,
            gcvSURF_A8R8G8B8,
            gcvPOOL_DEFAULT,
            &dstSurf
            ));

        srcRect.left   = 0;
        srcRect.top    = 0;
        srcRect.right  = 64;
        srcRect.bottom = 16;

        dstRect.left   = 0;
        dstRect.top    = 0;
        dstRect.right  = 128;
        dstRect.bottom = 32;

        gcmERR_BREAK(gcoSURF_FilterBlit(
            srcSurf,
            dstSurf,
            &srcRect,
            &dstRect,
            gcvNULL
            ));

        gcmERR_BREAK(gcoSURF_Destroy(srcSurf));
        srcSurf = gcvNULL;

        gcmERR_BREAK(gcoSURF_Destroy(dstSurf));
        dstSurf = gcvNULL;
    }
    while(gcvFALSE);

    if (gcmIS_ERROR(status)) {
        gcmTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_HAL,
            "Failed to workarond for GC300.");

        if (srcSurf)
        {
            gcmVERIFY_OK(gcoSURF_Destroy(srcSurf));
        }

        if (dstSurf)
        {
            gcmVERIFY_OK(gcoSURF_Destroy(dstSurf));
        }
    }

    return status;
}
예제 #19
0
static gceSTATUS
gcoBUFFER_GetCMDBUF(
    IN gcoBUFFER Buffer
    )
{
    gceSTATUS status;
    gcoCMDBUF command;
    gctSIZE_T index;
    gcePIPE_SELECT entryPipe;

    gcmHEADER_ARG("Buffer=0x%x", Buffer);

    /* Determine the next command buffer. */
    if (Buffer->currentCommandBuffer == gcvNULL)
    {
        /* First time - get the first buffer. */
        index = 0;

        /* Select 3D pipe for the first buffer. */
        entryPipe = gcvPIPE_3D;
    }
    else
    {
        /* Get current entry pipe. */
        entryPipe = Buffer->currentCommandBuffer->entryPipe;

        /* Determine the next command buffer index. */
        index = (Buffer->currentCommandBufferIndex + 1) % Buffer->count;
    }

    /* Test if command buffer is available. */
    status = gcoOS_WaitSignal(gcvNULL,
                              Buffer->signal[index],
                              0);

    if (status == gcvSTATUS_TIMEOUT)
    {
        if (Buffer->count < gcdMAX_CMD_BUFFERS)
        {
            do
            {
                if (Buffer->commandBuffers[Buffer->count] == gcvNULL)
                {
                    /* Construct a command buffer. */
                    gcmERR_BREAK(gcoCMDBUF_Construct(
                        gcvNULL,
                        gcvNULL,
                        Buffer->maxSize,
                        &Buffer->info,
                        &Buffer->commandBuffers[Buffer->count]));
                }

                if (Buffer->signal[Buffer->count] == gcvNULL)
                {
                    /* Create the signal. */
                    gcmERR_BREAK(gcoOS_CreateSignal(
                        gcvNULL,
                        gcvFALSE,
                        &Buffer->signal[Buffer->count]));

                    gcmTRACE_ZONE(
                        gcvLEVEL_INFO, gcvZONE_SIGNAL,
                        "%s(%d): buffer %d signal created 0x%08X",
                        __FUNCTION__, __LINE__,
                        Buffer->count, Buffer->signal[Buffer->count]);
                }

                /* Mark the buffer as available. */
                gcmERR_BREAK(gcoOS_Signal(gcvNULL,
                                          Buffer->signal[Buffer->count],
                                          gcvTRUE));

                /* Use the new buffer. */
                index          = Buffer->count;
                Buffer->count += 1;

                gcmTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_BUFFER,
                              "Using %lu command buffers.",
                              Buffer->count);
            }
            while (gcvFALSE);
        }

        /* Wait for buffer to become available. */
        gcmONERROR(gcoOS_WaitSignal(gcvNULL,
                                    Buffer->signal[index],
                                    gcPLS.hal->timeOut));
    }
    else
    {
        gcmONERROR(status);
    }

    /* Select new command buffer. */
    Buffer->currentCommandBufferIndex = index;
    Buffer->currentCommandBuffer      = Buffer->commandBuffers[index];

    /* Grab pointer to current command buffer. */
    command = Buffer->currentCommandBuffer;

    /* Set the entry pipe. */
    command->entryPipe = entryPipe;

    /* Reset command buffer. */
    command->startOffset = 0;
    command->offset      = Buffer->info.reservedHead;
    command->free        = command->bytes - Buffer->totalReserved;

    /* Succees. */
    gcmFOOTER_ARG("currentCommandBufferIndex=%d",
                  Buffer->currentCommandBufferIndex);
    return gcvSTATUS_OK;

OnError:
    /* Return the status. */
    gcmFOOTER();
    return status;
}
예제 #20
0
static gceSTATUS _DereferenceObjectCache(
	vgsCONTEXT_PTR Context,
	vgsOBJECT_CACHE_PTR * ObjectCache
	)
{
	/* Define the result and assume success. */
	gceSTATUS status = gcvSTATUS_OK;

	do
	{
		vgsOBJECT_PTR object;
		vgsOBJECT_LIST_PTR objectList;

		/* Get a shortcut to the object cache. */
		vgsOBJECT_CACHE_PTR objectCache = *ObjectCache;

		/* Existing object cache? */
		if (objectCache == gcvNULL)
		{
			break;
		}

		/* Valid reference count? */
		if (objectCache->referenceCount < 1)
		{
			gcmFATAL("Invalid reference count found.\n");
			status = gcvSTATUS_INVALID_OBJECT;
			break;
		}

		/* Decrement the counter. */
		objectCache->referenceCount--;

		/* Time to destroy? */
		if (objectCache->referenceCount == 0)
		{
			gctUINT i;

			/* Delete objects that are still in the cache. */
			for (i = 0; i < vgvOBJECTTYPE_COUNT; i++)
			{
				gctUINT32 index;

				/* Get the current object list. */
				objectList = &objectCache->cache[i];

				for (index = 0; index < vgvNAMED_OBJECTS_HASH; index++)
				{
					/* Are there objects in the list? */
					if (objectList->head[index] != gcvNULL)
					{
						gcmTRACE(
							gcvLEVEL_ERROR,
							"%s (%d): object cache %d still has objects in it.\n",
							__FUNCTION__, __LINE__, i
							);

						/* Delete the objects. */
						while (objectList->head[index])
                                        	{
							/* Copy the head object. */
							object = objectList->head[index];

							/* Dereference it. */
							gcmERR_BREAK(vgfDereferenceObject(
								Context,
								&object
								));
						}
					}
				 }

				/* Error? */
				if (gcmIS_ERROR(status))
				{
					break;
				}
			}

			/* Error? */
			if (gcmIS_ERROR(status))
			{
				break;
			}

			/* Allocate the context structure. */
			gcmERR_BREAK(gcoOS_Free(
				Context->os,
				(gctPOINTER *) objectCache
				));

			/* Reset the object. */
			*ObjectCache = gcvNULL;
		}
	}
	while (gcvFALSE);

	/* Return status. */
	return status;
}
static gceSTATUS
_MonoBlit(
    IN gcsCOPYBIT_CONTEXT * Context,
    IN gctUINT32 SourcePhysical,
    IN gctUINT32 SourceStride,
    IN gceSURF_FORMAT SourceFormat,
    IN gctUINT32 DestPhysical,
    IN gctUINT32 DestStride,
    IN gceSURF_FORMAT DestFormat,
    IN gcsRECT * Rect
    )
{
    gceSTATUS status = gcvSTATUS_OK;

    do
    {
        if ((Context->perpixelAlpha)
        ||  (Context->planeAlpha != 0xFF)
        )
        {
            gcmERR_BREAK(
                gco2D_DisableAlphaBlend(Context->engine));

            /* PlaneAlpha dirty. */
            Context->dirty.s.alphaKey = 1;
        }

        if ((Context->transform == COPYBIT_TRANSFORM_ROT_180)
        ||  (Context->transform == COPYBIT_TRANSFORM_FLIP_H)
        ||  (Context->transform == COPYBIT_TRANSFORM_FLIP_V)
        )
        {
            gcmERR_BREAK(
                gco2D_SetBitBlitMirror(Context->engine,
                                                gcvFALSE,
                                                gcvFALSE));

            /* Transform dirty. */
            Context->dirty.s.transformKey = 1;
        }

        gcmERR_BREAK(
            gco2D_SetColorSource(Context->engine,
                                 SourcePhysical,
                                 SourceStride,
                                 SourceFormat,
                                 gcvSURF_0_DEGREE,
                                 0,
                                 gcvFALSE,
                                 gcvSURF_OPAQUE,
                                 0));

        gcmERR_BREAK(
            gco2D_SetSource(Context->engine,
                            Rect));

        gcmERR_BREAK(
            gco2D_SetTarget(Context->engine,
                            DestPhysical,
                            DestStride,
                            gcvSURF_0_DEGREE,
                            0));

        gcmERR_BREAK(
            gco2D_SetClipping(Context->engine,
                              Rect));

        gcmERR_BREAK(
            gco2D_Blit(Context->engine,
                       1,
                       Rect,
                       0xCC,
                       0xCC,
                       DestFormat));
    }
    while (gcvFALSE);

    return status;
}
예제 #22
0
static gceSTATUS _ReferenceObjectCache(
	vgsCONTEXT_PTR Context,
	vgsOBJECT_CACHE_PTR * ObjectCache
	)
{
	gceSTATUS status, last;
	vgsOBJECT_CACHE_PTR objectCache = gcvNULL;

	do
	{
		/* Has the object cache been created? */
		if (*ObjectCache == gcvNULL)
		{
			static vgtSET_OBJECT_LIST initList[] =
			{
				vgfSetPathObjectList,
				vgfSetImageObjectList,
				vgfSetMaskObjectList,
				vgfSetFontObjectList,
				vgfSetPaintObjectList
			};

			gctUINT i;

			/* Allocate the context structure. */
			gcmERR_BREAK(gcoOS_Allocate(
				Context->os,
				gcmSIZEOF(vgsOBJECT_CACHE),
				(gctPOINTER *) &objectCache
				));

			gcmERR_BREAK(gcoOS_ZeroMemory(
				objectCache,
				gcmSIZEOF(vgsOBJECT_CACHE)));

			/* Initialize the object. */
			objectCache->loHandle       = ~0;
			objectCache->hiHandle       =  0;
			objectCache->referenceCount =  0;

			/* Initialize object arrays. */
			for (i = 0; i < gcmCOUNTOF(initList); i++)
			{
				initList[i] (&objectCache->cache[i]);
			}

			/* Set the result pointer. */
			*ObjectCache = objectCache;
		}

		/* Increment the counter. */
		(*ObjectCache)->referenceCount++;

		/* Success. */
		return gcvSTATUS_OK;
	}
	while (gcvFALSE);

	/* Roll back. */
	if (objectCache != gcvNULL)
	{
		gcmCHECK_STATUS(gcoOS_Free(Context->os, objectCache));
	}

	/* Return status. */
	return status;
}
static gceSTATUS
_UploadStates(
    IN gcsCOPYBIT_CONTEXT * Context
    )
{
    gceSTATUS status = gcvSTATUS_OK;

    do
    {
        if (Context->dirty.i == 0)
        {
            /* Done. */
            break;
        }

        /* rotationDeg. */
        if (Context->dirty.s.rotationDegKey)
        {
            /* TODO: rotationDeg. */
            Context->dirty.s.rotationDegKey = 0;
        }

        /* planeAlpha. */
        if (Context->dirty.s.alphaKey)
        {
            /* Setup alpha blending. */
            if ((Context->perpixelAlpha)
            ||  (Context->planeAlpha != 0xFF)
            )
            {
                gcmERR_BREAK(
                    gco2D_EnableAlphaBlend(Context->engine,
                                           Context->planeAlpha,
                                           Context->planeAlpha,
                                           gcvSURF_PIXEL_ALPHA_STRAIGHT,
                                           gcvSURF_PIXEL_ALPHA_STRAIGHT,
                                           gcvSURF_GLOBAL_ALPHA_SCALE,
                                           gcvSURF_GLOBAL_ALPHA_ON,
                                           gcvSURF_BLEND_STRAIGHT,
                                           gcvSURF_BLEND_INVERSED,
                                           gcvSURF_COLOR_STRAIGHT,
                                           gcvSURF_COLOR_STRAIGHT));
            }
            else
            {
                gcmERR_BREAK(
                    gco2D_DisableAlphaBlend(Context->engine));
            }

            Context->dirty.s.alphaKey = 0;
        }

        /* Dither. */
        if (Context->dirty.s.ditherKey)
        {
            /* TODO: Dither. */

            Context->dirty.s.ditherKey = 0;
        }

        /* Transform. */
        if (Context->dirty.s.transformKey)
        {
            Context->dstRotation   = gcvSURF_0_DEGREE;
            Context->srcRotation   = gcvSURF_0_DEGREE;
            gctBOOL horizonMirror  = gcvFALSE;
            gctBOOL verticalMirror = gcvFALSE;

            /* Setup transform */
            switch(Context->transform)
            {
            case COPYBIT_TRANSFORM_FLIP_H:
                horizonMirror = gcvTRUE;
                break;

            case COPYBIT_TRANSFORM_FLIP_V:
                verticalMirror = gcvTRUE;
                break;

            case COPYBIT_TRANSFORM_ROT_90:
                Context->dstRotation = gcvSURF_90_DEGREE;
                break;

            case COPYBIT_TRANSFORM_ROT_180:
                horizonMirror  = gcvTRUE;
                verticalMirror = gcvTRUE;
                break;

            case COPYBIT_TRANSFORM_ROT_270:
                Context->srcRotation = gcvSURF_90_DEGREE;
                break;

            default:
                break;
            }

            gcmERR_BREAK(
                gco2D_SetBitBlitMirror(Context->engine,
                                       horizonMirror,
                                       verticalMirror));

            Context->dirty.s.transformKey = 0;
        }

        /* Blur. */
        if (Context->dirty.s.blurKey)
        {
            /* TODO: Blur. */

            Context->dirty.s.blurKey = 0;
        }
    }
    while (gcvFALSE);

    return status;
}
gceSTATUS
_StretchBlitPE1x(
    IN gcsCOPYBIT_CONTEXT * Context,
    IN struct copybit_image_t const  * Dest,
    IN struct copybit_image_t const  * Source,
    IN struct copybit_rect_t const   * DestRect,
    IN struct copybit_rect_t const   * SourceRect,
    IN struct copybit_region_t const * Clip)
{
    gceSTATUS status = gcvSTATUS_OK;

    gceSURF_FORMAT siFormat;
    gceSURF_FORMAT diFormat;

    gctUINT32      diPhysical = ~0;
    gctUINT32      diAlignedWidth;
    gctUINT32      diAlignedHeight;
    gctINT         diStride;

    gcsRECT srcRect;
    gcsRECT dstRect;
    copybit_rect_t rect;

    gctUINT32      srcPhysical = ~0;
    gctINT         srcStride;
    gctUINT32      srcAlignedWidth;
    gctUINT32      srcAlignedHeight;
    gceSURF_FORMAT srcFormat;

    gctUINT32      dstPhysical = ~0;
    gctINT         dstStride;
    gctUINT32      dstAlignedWidth;
    gctUINT32      dstAlignedHeight;
    gceSURF_FORMAT dstFormat;

    gctBOOL stretch   = gcvFALSE;
    gctBOOL yuvFormat = gcvFALSE;
    gctBOOL perpixelAlpha;

    gc_private_handle_t* dsthnd = (gc_private_handle_t *) Dest->handle;
    gc_private_handle_t* srchnd = (gc_private_handle_t *) Source->handle;

    LOGV("Blit from Source hnd=%p, to Dest hnd=%p", srchnd, dsthnd);

    if (gc_private_handle_t::validate(dsthnd) < 0)
    {
        gcmTRACE(gcvLEVEL_ERROR,
                 "Invalid hnd in funciton %s",
                 __func__);

        return gcvSTATUS_INVALID_ARGUMENT;
    }

    siFormat = (gceSURF_FORMAT) srchnd->format;
    diFormat = (gceSURF_FORMAT) dsthnd->format;

    if ((siFormat == gcvSURF_UNKNOWN)
    ||  (diFormat == gcvSURF_UNKNOWN)
    )
    {
        gcmTRACE(gcvLEVEL_ERROR,
                 "Image format not support in copybit!");

        return gcvSTATUS_INVALID_ARGUMENT;
    }

    /* Convert to supported Source format. */
    siFormat = (siFormat == gcvSURF_A8B8G8R8) ? gcvSURF_A8R8G8B8 : siFormat;
    siFormat = (siFormat == gcvSURF_X8B8G8R8) ? gcvSURF_X8R8G8B8 : siFormat;

    /* Convert to supported Dest format. */
    diFormat = (diFormat == gcvSURF_A8B8G8R8) ? gcvSURF_A8R8G8B8 : diFormat;
    diFormat = (diFormat == gcvSURF_X8B8G8R8) ? gcvSURF_X8R8G8B8 : diFormat;

    do
    {
        srcPhysical = srchnd->phys;
        gcoSURF_GetAlignedSize((gcoSURF) srchnd->surface,
                               &srcAlignedWidth,
                               &srcAlignedHeight,
                               &srcStride);

        diPhysical = dsthnd->phys;
        gcoSURF_GetAlignedSize((gcoSURF) dsthnd->surface,
                               &diAlignedWidth,
                               &diAlignedHeight,
                               &diStride);

        if  ((((gcoSURF)srchnd->surface)->info.type == gcvSURF_BITMAP) &&
            !(srchnd->flags & gc_private_handle_t::PRIV_FLAGS_FRAMEBUFFER))
        {
            /* Clean the CPU cache. Source would've been rendered by the CPU. */
            gcmERR_BREAK(
                gcoSURF_CPUCacheOperation(
                            (gcoSURF) srchnd->surface,
                            gcvCACHE_CLEAN
                            )
            );
        }

        perpixelAlpha = _HasAlpha(siFormat) &&
                 (dsthnd->flags & gc_private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
                 !(srchnd->flags & gc_private_handle_t::PRIV_FLAGS_FRAMEBUFFER);

        if (Context->perpixelAlpha != perpixelAlpha)
        {
            Context->perpixelAlpha = perpixelAlpha;

            if (Context->planeAlpha == 0xff)
            {
                Context->dirty.s.alphaKey = 1;
            }
        }

        /* Need temp surface if source has alpha channel, but dest not. */
        Context->needAlphaDest = Context->perpixelAlpha &&
                !_HasAlpha(diFormat);

        if (Context->needAlphaDest)
        {
            gcsRECT tempRect;

            tempRect.left   = gcmMAX(0, DestRect->l);
            tempRect.top    = gcmMAX(0, DestRect->t);
            tempRect.right  = gcmMIN((int32_t) Dest->w, DestRect->r);
            tempRect.bottom = gcmMIN((int32_t) Dest->h, DestRect->b);

            gcmERR_BREAK(
                _FitSurface(Context,
                            &Context->alphaDest,
                            Dest->w,
                            Dest->h));

            if (Context->alphaDest.surface == gcvNULL)
            {
                gcmTRACE(gcvLEVEL_ERROR,
                         "fail to construct tmp surface for per_pixel_alpha");

                break;
            }

            /* Copy dest surface to temp surface. */
            gcmERR_BREAK(
                _MonoBlit(Context,
                          diPhysical,
                          diStride,
                          diFormat,
                          Context->alphaDest.physical,
                          Context->alphaDest.stride,
                          Context->alphaDest.format,
                          &tempRect));
        }

        gcmERR_BREAK(
            _UploadStates(Context));

        if (Context->needAlphaDest)
        {
            dstPhysical      = Context->alphaDest.physical;
            dstStride        = Context->alphaDest.stride;
            dstAlignedWidth  = Context->alphaDest.alignedWidth;
            dstAlignedHeight = Context->alphaDest.alignedHeight;
            dstFormat        = Context->alphaDest.format;
        }
        else
        {
            dstPhysical      = diPhysical;
            dstStride        = diStride;
            dstAlignedWidth  = diAlignedWidth;
            dstAlignedHeight = diAlignedHeight;
            dstFormat        = diFormat;
        }

        srcFormat = siFormat;

        if (Context->transform == COPYBIT_TRANSFORM_ROT_270)
        {
            srcRect.left   = SourceRect->t;
            srcRect.top    = Source->w - SourceRect->r;
            srcRect.right  = SourceRect->b;
            srcRect.bottom = Source->w - SourceRect->l;
        }
        else
        {
            srcRect.left   = SourceRect->l;
            srcRect.top    = SourceRect->t;
            srcRect.right  = SourceRect->r;
            srcRect.bottom = SourceRect->b;
        }

        if (Context->transform ==  COPYBIT_TRANSFORM_ROT_90)
        {
            dstRect.left   = DestRect->t;
            dstRect.top    = Dest->w - DestRect->r;
            dstRect.right  = DestRect->b;
            dstRect.bottom = Dest->w - DestRect->l;
        }
        else
        {
            dstRect.left   = DestRect->l;
            dstRect.top    = DestRect->t;
            dstRect.right  = DestRect->r;
            dstRect.bottom = DestRect->b;
        }

        /* Check yuv format. */
        yuvFormat = (srcFormat == gcvSURF_YUY2 || srcFormat == gcvSURF_UYVY);

        stretch =
            (srcRect.right - srcRect.left) != (dstRect.right - dstRect.left) ||
            (srcRect.bottom - srcRect.top) != (dstRect.bottom - dstRect.top);

        /* Upload stretch factor. */
        if (stretch)
        {
            int hFactor;
            int vFactor;

            if ((dstRect.right-dstRect.left) > 1 && (dstRect.bottom-dstRect.top) > 1)
            {
                hFactor = ((srcRect.right - srcRect.left - 1) << 16) /
                        (dstRect.right - dstRect.left - 1);

                vFactor = ((srcRect.bottom - srcRect.top - 1) << 16) /
                        (dstRect.bottom - dstRect.top - 1);
            }
            else
            {
                hFactor = 0;
                vFactor = 0;
            }

            gcmERR_BREAK(
                gco2D_SetStretchFactors(Context->engine,
                                        hFactor,
                                        vFactor));
        }

        /* Prepare source and target for normal blit. */
        gcmERR_BREAK(
            gco2D_SetColorSource(Context->engine,
                                 srcPhysical,
                                 srcStride,
                                 srcFormat,
                                 Context->srcRotation,
                                 srcAlignedWidth,
                                 gcvFALSE,
                                 gcvSURF_OPAQUE,
                                 0));

        gcmERR_BREAK(
            gco2D_SetSource(Context->engine,
                            &srcRect));

        gcmERR_BREAK(
            gco2D_SetTarget(Context->engine,
                            dstPhysical,
                            dstStride,
                            Context->dstRotation,
                            dstAlignedWidth));

        gcsRECT srcRectBackup = srcRect;
        gcsRECT dstRectBackup = dstRect;

        /* Go though all clip rectangles. */
        while (Clip->next(Clip, &rect))
        {
            gcsRECT clipRect;

            srcRect = srcRectBackup;
            dstRect = dstRectBackup;

            if (Context->transform ==  COPYBIT_TRANSFORM_ROT_90)
            {
                clipRect.left   = rect.t;
                clipRect.top    = Dest->w - rect.r;
                clipRect.right  = rect.b;
                clipRect.bottom = Dest->w - rect.l;
            }
            else if (Context->transform == COPYBIT_TRANSFORM_ROT_180)
            {
                float hfactor = (float) (SourceRect->r - SourceRect->l)
                                 / (DestRect->r - DestRect->l);

                float vfactor = (float) (SourceRect->b - SourceRect->t)
                                 / (DestRect->b - DestRect->t);

                /* Intersect. */
                clipRect.left   = gcmMAX(dstRect.left, rect.l);
                clipRect.top    = gcmMAX(dstRect.top, rect.t);
                clipRect.right  = gcmMIN(dstRect.right, rect.r);
                clipRect.bottom = gcmMIN(dstRect.bottom, rect.b);

                /* Adjust src rectangle. */
                srcRect.left   += (int) ((dstRect.right - clipRect.right) * hfactor);
                srcRect.top    += (int) ((dstRect.bottom - clipRect.bottom) * vfactor);
                srcRect.right  -= (int) ((clipRect.left - dstRect.left) * hfactor);
                srcRect.bottom -= (int) ((clipRect.top - dstRect.top) * vfactor);

                /* Set dstRect to clip rectangle. */
                dstRect = clipRect;

                if ((srcRect.left   != srcRectBackup.left)
                ||  (srcRect.right  != srcRectBackup.right)
                ||  (srcRect.top    != srcRectBackup.top)
                ||  (srcRect.bottom != srcRectBackup.bottom)
                )
                {
                    gcmERR_BREAK(
                        gco2D_SetSource(Context->engine,
                                        &srcRect));
                }
            }
            else
            {
                clipRect.left   = rect.l;
                clipRect.top    = rect.t;
                clipRect.right  = rect.r;
                clipRect.bottom = rect.b;
            }

            /* Clamp clip rectangle. */
            if (clipRect.right > dstRect.right)
                clipRect.right = dstRect.right;

            if (clipRect.bottom > dstRect.bottom)
                clipRect.bottom = dstRect.bottom;

            if (clipRect.left < dstRect.left)
                clipRect.left = dstRect.left;

            if (clipRect.top < dstRect.top)
                clipRect.top = dstRect.top;

            gcmERR_BREAK(
                gco2D_SetClipping(Context->engine,
                                  &clipRect));

            if (yuvFormat)
            {
                /* TODO: FilterBlit does not support rotation before PE20. */
                /* Video filter blit */
                /* 1. SetClipping() has no effect for FilterBlit()
                 *    so we use dstSubRect to realize clipping effect
                 * 2. Only FilterBlit support yuv format covertion.
                 */
                gcsRECT dstSubRect;
                int dstWidth   = dstRect.right   - dstRect.left;
                int dstHeight  = dstRect.bottom  - dstRect.top;
                int clipWidth  = clipRect.right  - clipRect.left;
                int clipHeight = clipRect.bottom - clipRect.top;

                dstSubRect.left   = clipRect.left - dstRect.left;
                dstSubRect.top    = clipRect.top - dstRect.top;
                dstSubRect.right  = dstWidth < clipWidth ?
                        dstSubRect.left + dstWidth :
                        dstSubRect.left + clipWidth;
                dstSubRect.bottom = dstHeight < clipHeight ?
                        dstSubRect.top  + dstHeight :
                        dstSubRect.top  + clipHeight;

                gcmERR_BREAK(
                    gco2D_SetKernelSize(Context->engine,
                                        gcdFILTER_BLOCK_SIZE,
                                        gcdFILTER_BLOCK_SIZE));

                gcmERR_BREAK(
                    gco2D_SetFilterType(Context->engine,
                                        gcvFILTER_SYNC));

                gcmERR_BREAK(
                    gco2D_FilterBlit(Context->engine,
                                     srcPhysical,
                                     srcStride,
                                     0, 0, 0, 0,
                                     srcFormat,
                                     Context->srcRotation,
                                     srcAlignedWidth,
                                     &srcRect,
                                     dstPhysical,
                                     dstStride,
                                     dstFormat,
                                     Context->dstRotation,
                                     dstAlignedWidth,
                                     &dstRect,
                                     &dstSubRect));
            }
            else if (Context->blur)
            {
                /* TODO: FilterBlit does not support rotation before PE20. */
                gcsRECT dstSubRect;
                dstSubRect.left  = 0;
                dstSubRect.top   = 0;
                dstSubRect.right = dstRect.right - dstRect.left;
                dstSubRect.bottom = dstRect.bottom - dstRect.top;

                /* Blur blit. */
                gcmERR_BREAK(
                    gco2D_SetKernelSize(Context->engine,
                                        gcdFILTER_BLOCK_SIZE,
                                        gcdFILTER_BLOCK_SIZE));

                gcmERR_BREAK(
                    gco2D_SetFilterType(Context->engine,
                                        gcvFILTER_BLUR));

                gcmERR_BREAK(
                    gco2D_FilterBlit(Context->engine,
                                     srcPhysical,
                                     srcStride,
                                     0, 0, 0, 0,
                                     srcFormat,
                                     gcvSURF_0_DEGREE,
                                     srcAlignedWidth,
                                     &srcRect,
                                     dstPhysical,
                                     dstStride,
                                     dstFormat,
                                     gcvSURF_0_DEGREE,
                                     dstAlignedWidth,
                                     &dstRect,
                                     &dstSubRect));

                gcmERR_BREAK(
                    gco2D_FilterBlit(Context->engine,
                                     dstPhysical,
                                     dstStride,
                                     0, 0, 0, 0,
                                     dstFormat,
                                     gcvSURF_0_DEGREE,
                                     dstAlignedWidth,
                                     &dstRect,
                                     dstPhysical,
                                     dstStride,
                                     dstFormat,
                                     gcvSURF_0_DEGREE,
                                     dstAlignedWidth,
                                     &dstRect,
                                     &dstSubRect));

                /* TODO: surfaceflinger set blur issue. */
                Context->blur = COPYBIT_DISABLE;
            }
            else if (stretch == gcvFALSE)
            {
                /* BitBlit. */
                gcmERR_BREAK(
                    gco2D_Blit(Context->engine,
                               1,
                               &dstRect,
                               0xCC,
                               0xCC,
                               dstFormat));
            }
            else
            {
                /* Normal stretch blit. */
                gcmERR_BREAK(
                    gco2D_StretchBlit(Context->engine,
                                      1,
                                      &dstRect,
                                      0xCC,
                                      0xCC,
                                      dstFormat));
            }
        }

        if (gcmIS_ERROR(status))
        {
            break;
        }

        if (Context->needAlphaDest)
        {
            gcsRECT tempRect;

            tempRect.left   = gcmMAX(0, DestRect->l);
            tempRect.top    = gcmMAX(0, DestRect->t);
            tempRect.right  = gcmMIN((int32_t) Dest->w, DestRect->r);
            tempRect.bottom = gcmMIN((int32_t) Dest->h, DestRect->b);

            /* Blit back to actual dest. */
            gcmERR_BREAK(
                _MonoBlit(Context,
                          Context->alphaDest.physical,
                          Context->alphaDest.stride,
                          Context->alphaDest.format,
                          diPhysical,
                          diStride,
                          diFormat,
                          &tempRect));
        }

        /* Flush and commit. */
        gcmERR_BREAK(
            gco2D_Flush(Context->engine));

        gcmERR_BREAK(
            gcoHAL_Commit(gcvNULL, gcvFALSE));
    }
    while (gcvFALSE);

    return status;
}
예제 #25
0
/*******************************************************************************
**
**  gcoDUMP_Control
**
**  Control dumping.
**
**  INPUT:
**
**      gcoDUMP Dump
**          Pointer to a gcoDUMP object.
**
**      gctSTRING FileName
**          If 'FileName' is not gcvNULL, it points to the filename to be used for
**          capturing all data.  If 'FileName' is gcvNULL, turn off any current
**          capturing.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoDUMP_Control(
    IN gcoDUMP Dump,
    IN gctSTRING FileName
    )
{
    gceSTATUS status = gcvSTATUS_OK;
    gcsDUMP_FILE header;
    gctUINT32 pos;

    gcmHEADER_ARG("Dump=0x%x FileName=0x%x", Dump, FileName);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP);

    do
    {
        if (FileName != gcvNULL)
        {
            /* Need to create a new dump file. */
            if (Dump->file == gcvNULL)
            {
                /* Create the dump file. */
                gcmERR_BREAK(gcoOS_Open(gcvNULL,
                                    FileName,
                                    gcvFILE_CREATE,
                                    &Dump->file));

                /* Write the file header. */
                header.signature   = gcvDUMP_FILE_SIGNATURE;
                header.length      = Dump->length     = 0;
                header.frames      = Dump->frameCount = 0;

                gcmERR_BREAK(gcoOS_Write(gcvNULL,
                                     Dump->file,
                                     sizeof(header),
                                     &header));

                /* Frame is not yet started. */
                Dump->frameStart = 0;
            }
        }
        else
        {
            /* Need to close any current dump file. */
            if (Dump->file != gcvNULL)
            {
                /* Close any open frame. */
                if (Dump->frameStart != 0)
                {
                    gcoDUMP_FrameEnd(Dump);
                    gcoDUMP_FrameBegin(Dump);
                }

                /* Get the current position. */
                gcmERR_BREAK(gcoOS_GetPos(gcvNULL, Dump->file, &pos));

                /* Seek to the beginnnig of the file. */
                gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, 0));

                /* Make sure we have the correct size. */
                gcmASSERT(pos == Dump->length + sizeof(header));

                /* Update the file header. */
                header.signature = gcvDUMP_FILE_SIGNATURE;
                header.length    = Dump->length;
                header.frames    = Dump->frameCount;

                gcmERR_BREAK(gcoOS_Write(gcvNULL,
                                     Dump->file,
                                     sizeof(header),
                                     &header));

                /* Seek to the end of the file. */
                gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, pos));

                /* Close the file. */
                gcmERR_BREAK(gcoOS_Close(gcvNULL, Dump->file));

                /* Mark the file as closed. */
                Dump->file = gcvNULL;
            }
        }
    }
    while (gcvFALSE);

    /* Return the status. */
    gcmFOOTER();
    return status;
}
gceSTATUS glfCreateNamedObject(
	IN glsCONTEXT_PTR Context,
	IN glsNAMEDOBJECTLIST_PTR List,
	IN gctUINT32 Name,
	IN glfNAMEDOBJECTDESTRUCTOR ObjectDestructor,
	OUT glsNAMEDOBJECT_PTR * ObjectWrapper
	)
{
    gceSTATUS status = gcvSTATUS_OK;
    gcmHEADER_ARG("Context=0x%x List=0x%x Name=%u ObjectDestructor=0x%x ObjectWrapper=0x%x",
                    Context, List, Name, ObjectDestructor, ObjectWrapper);

	do
	{
		glsNAMEDOBJECT_PTR wrapper;
		glsNAMEDOBJECT_PTR* entry;
		gctUINT32 index;

		/* Are there available wrappers in the free list? */
		wrapper = List->freeList;
		if ((Name == 0) && (wrapper != gcvNULL))
		{
			/* Remove the first wrapper from the list. */
			List->freeList = wrapper->next;
		}

		/* Create a new wrapper. */
		else
		{
			/* Create a new wrapper. */
			wrapper = gcvNULL;

			/* Generate a name if not specified. */
			if (Name == 0)
			{
				if (List->nextName == 0)
				{
					/* No more names. */
					status = gcvSTATUS_OUT_OF_RESOURCES;
					break;
				}

				Name = List->nextName++;
			}
			else if (Name > List->nextName)
			{
				/* Name for the object has been explicitly specified by
				   the application and it is greater then the next automatic
				   would-be name. Update the next name with the value from
				   the application; this creates a hole in the name range. */
				List->nextName = Name + 1;
			}
			else if (List->freeList != gcvNULL)
			{
				/* Name for the object has been explicitly specified by
				   the application and it is less then or equal to the next
				   automatic would-be name.  This means the name most likely
				   lives inside the free list. */
				if (List->freeList->name == Name)
				{
					wrapper        = List->freeList;
					List->freeList = wrapper->next;
				}
				else
				{
					glsNAMEDOBJECT_PTR previous = List->freeList;

					for (wrapper = List->freeList;
						 wrapper != gcvNULL;
						 wrapper = wrapper->next)
					{
						if (wrapper->name == Name)
						{
							previous->next = wrapper->next;
							break;
						}

						previous = wrapper;
					}
				}
			}

			if (wrapper == gcvNULL)
			{
				/* Allocate wrapper and the user object. */
				gcmERR_BREAK(gcoOS_Allocate(
					gcvNULL,
					gcmALIGN(sizeof(glsNAMEDOBJECT), 4) + List->objectSize,
					(gctPOINTER) &wrapper
					));

				/* Set the objects's name. */
				wrapper->name = Name;

				/* Set the object pointer. */
				wrapper->object
					= ((gctUINT8_PTR) wrapper)
					+ gcmALIGN(sizeof(glsNAMEDOBJECT), 4);

                wrapper->referenceCount = 0;

                wrapper->listBelonged = List;
			}
		}

		/* Set the destructor. */
		wrapper->deleteObject = ObjectDestructor;

		/* Determine the hash table index. */
		index = wrapper->name % glvNAMEDOBJECT_HASHTABLE_SIZE;

		/* Shortcut to the table entry. */
		entry = &List->hashTable[index];

		/* Insert into the chain. */
		wrapper->next = *entry;
		*entry = wrapper;

        glfReferenceNamedObject(wrapper);

		/* Set the result. */
		*ObjectWrapper = wrapper;
	}
	while (gcvFALSE);

    gcmFOOTER();

	return status;
}
예제 #27
0
gceSTATUS
_FitSurface(
    IN gcsCOPYBIT_CONTEXT * Context,
    IN gcsSURFACE * Surface,
    IN gctUINT32 Width,
    IN gctUINT32 Height
    )
{
    gceSTATUS status = gcvSTATUS_OK;

    if (Surface == gcvNULL)
    {
        return gcvSTATUS_INVALID_ARGUMENT;
    }

    do
    {
        /* Create the tmp Surfaceace if necessary. */
        if ((Surface->surface == gcvNULL)
        ||  (Surface->width  < Width)
        ||  (Surface->height < Height)
        )
        {
            /* Destroy last surface. */
            if (Surface->surface != gcvNULL)
            {
                if (Surface->logical != gcvNULL)
                {
                    gcmERR_BREAK(
                        gcoSURF_Unlock(Surface->surface,
                                       Surface->logical));
                }

                gcmERR_BREAK(
                    gcoSURF_Destroy(Surface->surface));
            }

            /* New surface values. */
            Surface->format = gcvSURF_A8R8G8B8;
            Surface->width  = Width;
            Surface->height = Height;

            gcmERR_BREAK(
                gcoSURF_Construct(gcvNULL,
                                  Surface->width,
                                  Surface->height,
                                  1,
                                  gcvSURF_BITMAP,
                                  Surface->format,
                                  gcvPOOL_DEFAULT,
                                  &Surface->surface));

            gcmERR_BREAK(
                gcoSURF_Lock(Surface->surface,
                             &Surface->physical,
                             &Surface->logical));

            gcmERR_BREAK(
                gcoSURF_GetAlignedSize(Surface->surface,
                                       &Surface->alignedWidth,
                                       &Surface->alignedHeight,
                                       &Surface->stride));

        }
    }
    while (gcvFALSE);

    return status;
}