コード例 #1
0
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;
}
コード例 #2
0
gceSTATUS
gckIOMMU_Construct(
    IN gckOS Os,
    OUT gckIOMMU * Iommu
    )
{
    gceSTATUS status;
    gckIOMMU iommu = gcvNULL;
    struct device *dev;
    int ret;

    gcmkHEADER();

    dev = &Os->device->platform->device->dev;

    gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsIOMMU), (gctPOINTER *)&iommu));

    gckOS_ZeroMemory(iommu, gcmSIZEOF(gcsIOMMU));

    iommu->domain = iommu_domain_alloc(&platform_bus_type);

    if (!iommu->domain)
    {
        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "iommu_domain_alloc() fail");

        gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
    }

    iommu_set_fault_handler(iommu->domain, _IOMMU_Fault_Handler, dev);

    ret = iommu_attach_device(iommu->domain, dev);

    if (ret)
    {
        gcmkTRACE_ZONE(
            gcvLEVEL_INFO, gcvZONE_OS, "iommu_attach_device() fail %d", ret);

        gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
    }

    iommu->device = dev;

    _FlatMapping(iommu);

    *Iommu = iommu;

    gcmkFOOTER_NO();
    return gcvSTATUS_OK;

OnError:

    gckIOMMU_Destory(Os, iommu);

    gcmkFOOTER();
    return status;
}
コード例 #3
0
gceSTATUS
gcfDump(
    IN gcoOS Os,
    IN gctCONST_STRING Message,
    ...
    )
{

    gctUINT offset = 0;
    gctARGUMENTS args;
    char buffer[80];

    if (!setDumpFlag)
        return gcvSTATUS_OK;

#if gcdDUMP_IN_KERNEL
    gcsHAL_INTERFACE ioctl;

    gcmARGUMENTS_START(args, Message);
    gcmVERIFY_OK(gcoOS_PrintStrVSafe(ioctl.u.Debug.message,
                                     gcmSIZEOF(ioctl.u.Debug.message),
                                     &offset,
                                     Message, args));
    gcmARGUMENTS_END(args);

    ioctl.command     = gcvHAL_DEBUG;
    ioctl.u.Debug.set = gcvFALSE;
#if gcdDUMP
    ioctl.u.Debug.type = gcvMESSAGE_TEXT;
#else
    ioctl.u.Debug.type = gcvMESSAGE_DUMP;
#endif
    ioctl.u.Debug.messageSize = (gctUINT32)gcmSIZEOF(ioctl.u.Debug.message);

    gcmVERIFY_OK(gcoOS_DeviceControl(Os,
                                     IOCTL_GCHAL_INTERFACE,
                                     &ioctl, gcmSIZEOF(ioctl),
                                     &ioctl, gcmSIZEOF(ioctl)));
#else

    gcmARGUMENTS_START(args, Message);
    gcmVERIFY_OK(gcoOS_PrintStrVSafe(buffer, gcmSIZEOF(buffer),
                                     &offset,
                                     Message, args));
    gcmARGUMENTS_END(args);

    gcoOS_Print("%s", buffer);
#endif

    return gcvSTATUS_OK;
}
コード例 #4
0
static gceSTATUS
_Print(
	_VGContext * Context,
	gctCONST_STRING Format,
	...
	)
{
	char buffer[256];
	gctUINT offset = 0;
	gceSTATUS status;

	gcmONERROR(
		gcoOS_PrintStrVSafe(buffer, gcmSIZEOF(buffer),
							&offset,
							Format,
							(gctPOINTER) (&Format + 1)));

	gcmONERROR(
		gcoPROFILER_Write(Context->hal,
                          offset,
                          buffer));

	return gcvSTATUS_OK;

OnError:
	return status;
}
コード例 #5
0
static void
OutputDebugString(
    IN gctCONST_STRING String
    )
{
#if gcdBUFFERED_OUTPUT
    static gctCHAR outputBuffer[gcdBUFFERED_OUTPUT];
    static gctINT outputBufferIndex = 0;
    gctINT n, i;

    n = (String != gcvNULL) ? strlen(String) + 1 : 0;

    if ((n == 0) || (outputBufferIndex + n > gcmSIZEOF(outputBuffer)))
    {
        for (i = 0; i < outputBufferIndex; i += strlen(outputBuffer + i) + 1)
        {
            printk(outputBuffer + i);
        }

        outputBufferIndex = 0;
    }

    if (n > 0)
    {
        memcpy(outputBuffer + outputBufferIndex, String, n);
        outputBufferIndex += n;
    }
#else
    if (String != gcvNULL)
    {
        printk(String);
    }
#endif
}
コード例 #6
0
gceSTATUS
gckKERNEL_DumpProcessDB(
    IN gckKERNEL Kernel
    )
{
    gcsDATABASE_PTR database;
    gctINT i, pid;
    gctUINT8 name[24];

    gcmkHEADER_ARG("Kernel=0x%x", Kernel);

    /* Acquire the database mutex. */
    gcmkVERIFY_OK(
        gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));

    gcmkPRINT("**************************\n");
    gcmkPRINT("***  PROCESS DB DUMP   ***\n");
    gcmkPRINT("**************************\n");

    gcmkPRINT_N(8, "%-8s%s\n", "PID", "NAME");
    /* Walk the databases. */
    for (i = 0; i < gcmCOUNTOF(Kernel->db->db); ++i)
    {
        for (database = Kernel->db->db[i];
             database != gcvNULL;
             database = database->next)
        {
            pid = database->processID;

            gcmkVERIFY_OK(gckOS_ZeroMemory(name, gcmSIZEOF(name)));

            gcmkVERIFY_OK(gckOS_GetProcessNameByPid(pid, gcmSIZEOF(name), name));

            gcmkPRINT_N(8, "%-8d%s\n", pid, name);
        }
    }

    /* Release the database mutex. */
    gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));

    /* Success. */
    gcmkFOOTER_NO();
    return gcvSTATUS_OK;
}
コード例 #7
0
gceSTATUS
gcoQUEUE_Commit(
    IN gcoQUEUE Queue
    )
{
    gceSTATUS status = gcvSTATUS_OK;
    gcsHAL_INTERFACE iface;

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

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Queue, gcvOBJ_QUEUE);

    if (Queue->head != gcvNULL)
    {
        /* Initialize event commit command. */
        iface.command       = gcvHAL_EVENT_COMMIT;
        iface.u.Event.queue = Queue->head;

        /* Send command to kernel. */
        gcmONERROR(
            gcoOS_DeviceControl(gcvNULL,
                                IOCTL_GCHAL_INTERFACE,
                                &iface, gcmSIZEOF(iface),
                                &iface, gcmSIZEOF(iface)));

        /* Test for error. */
        gcmONERROR(iface.status);

        /* Free any records in the queue. */
        gcmONERROR(gcoQUEUE_Free(Queue));
    }

    /* Success. */
    gcmFOOTER_NO();
    return gcvSTATUS_OK;

OnError:
    /* Return the status. */
    gcmFOOTER();
    return status;
}
コード例 #8
0
void
_glshInitializeRenderbuffer(
    GLContext Context
    )
{
    /* No renderbuffers bound yet. */
    Context->renderbuffer = gcvNULL;

    /* No frame buffer objects. */
    gcmVERIFY_OK(gcoOS_ZeroMemory(&Context->renderbufferObjects,
                                  gcmSIZEOF(Context->renderbufferObjects)));
}
コード例 #9
0
/*******************************************************************************
**
**  _Split
**
**  Split a node on the required byte boundary.
**
**  INPUT:
**
**      gckOS Os
**          Pointer to an gckOS object.
**
**      gcuVIDMEM_NODE_PTR Node
**          Pointer to the node to split.
**
**      gctSIZE_T Bytes
**          Number of bytes to keep in the node.
**
**  OUTPUT:
**
**      Nothing.
**
**  RETURNS:
**
**      gctBOOL
**          gcvTRUE if the node was split successfully, or gcvFALSE if there is an
**          error.
**
*/
static gctBOOL
_Split(
    IN gckOS Os,
    IN gcuVIDMEM_NODE_PTR Node,
    IN gctSIZE_T Bytes
    )
{
    gcuVIDMEM_NODE_PTR node;

    /* Make sure the byte boundary makes sense. */
    if ((Bytes <= 0) || (Bytes > Node->VidMem.bytes))
    {
        return gcvFALSE;
    }

    /* Allocate a new gcuVIDMEM_NODE object. */
    if (gcmIS_ERROR(gckOS_Allocate(Os,
                                   gcmSIZEOF(gcuVIDMEM_NODE),
                                   (gctPOINTER *) &node)))
    {
        /* Error. */
        return gcvFALSE;
    }

    /* Initialize gcuVIDMEM_NODE structure. */
    node->VidMem.offset    = Node->VidMem.offset + Bytes;
    node->VidMem.bytes     = Node->VidMem.bytes  - Bytes;
    node->VidMem.alignment = 0;
    node->VidMem.locked    = 0;
    node->VidMem.memory    = Node->VidMem.memory;
    node->VidMem.pool      = Node->VidMem.pool;
    node->VidMem.physical  = Node->VidMem.physical;
#ifdef __QNXNTO__
    node->VidMem.logical   = gcvNULL;
    node->VidMem.handle    = 0;
#endif

    /* Insert node behind specified node. */
    node->VidMem.next = Node->VidMem.next;
    node->VidMem.prev = Node;
    Node->VidMem.next = node->VidMem.next->VidMem.prev = node;

    /* Insert free node behind specified node. */
    node->VidMem.nextFree = Node->VidMem.nextFree;
    node->VidMem.prevFree = Node;
    Node->VidMem.nextFree = node->VidMem.nextFree->VidMem.prevFree = node;

    /* Adjust size of specified node. */
    Node->VidMem.bytes = Bytes;

    /* Success. */
    return gcvTRUE;
}
コード例 #10
0
/**
 *
 * @param Hal
 * @param Node
 * @return
 */
static gceSTATUS UnlockVideoNode(
	IN gcoHAL Hal,
	IN gcuVIDMEM_NODE_PTR Node,
	IN gceSURF_TYPE surftype) {

	gcsHAL_INTERFACE iface;
	gceSTATUS status;

	gcmASSERT(Node != gcvNULL);

	iface.command = gcvHAL_UNLOCK_VIDEO_MEMORY;
	iface.u.UnlockVideoMemory.node = Node;
	iface.u.UnlockVideoMemory.type = surftype;
	iface.u.UnlockVideoMemory.asynchroneous = gcvTRUE;

	/* Call the kernel. */
	gcmONERROR(gcoOS_DeviceControl(
				gcvNULL,
				IOCTL_GCHAL_INTERFACE,
				&iface, gcmSIZEOF(iface),
				&iface, gcmSIZEOF(iface)
	));

	/* Success? */
	gcmONERROR(iface.status);

	/* Do we need to schedule an event for the unlock? */
	if (iface.u.UnlockVideoMemory.asynchroneous)
	{
		iface.u.UnlockVideoMemory.asynchroneous = gcvFALSE;
		gcmONERROR(gcoHAL_ScheduleEvent(Hal, &iface));
	}

OnError:
    /* Call kernel API. */
    return gcvSTATUS_FALSE;

}
コード例 #11
0
static gceSTATUS
_AddMap(
	IN gckOS Os,
	IN gctPOINTER Source,
	IN gctSIZE_T Bytes,
	OUT gctPOINTER * Destination,
	IN OUT gcsMAPPED_PTR * Stack
	)
{
	gcsMAPPED_PTR map = gcvNULL;
	gceSTATUS status;

	/* Don't try to map NULL pointers. */
	if (Source == gcvNULL)
	{
		*Destination = gcvNULL;
		return gcvSTATUS_OK;
	}

	/* Allocate the gcsMAPPED structure. */
	gcmkONERROR(
		gckOS_Allocate(Os, gcmSIZEOF(*map), (gctPOINTER *) &map));

	/* Map the user pointer into kernel addressing space. */
	gcmkONERROR(
		gckOS_MapUserPointer(Os, Source, Bytes, Destination));

	/* Save mapping. */
	map->pointer       = Source;
	map->kernelPointer = *Destination;
	map->bytes         = Bytes;

	/* Push structure on top of the stack. */
	map->next = *Stack;
	*Stack    = map;

	/* Success. */
	return gcvSTATUS_OK;

OnError:
	if (gcmIS_ERROR(status) && (map != gcvNULL))
	{
		/* Roll back on error. */
		gcmkVERIFY_OK(gckOS_Free(Os, map));
	}

	/* Return the status. */
	return status;
}
コード例 #12
0
/*******************************************************************************
**
**  gcoHAL_Construct
**
**  Construct a new gcoHAL object.
**
**  INPUT:
**
**      gctPOINTER Context
**          Pointer to a context that can be used by the platform specific
**          functions.
**
**      gcoOS Os
**          Pointer to an gcoOS object.
**
**  OUTPUT:
**
**      gcoHAL * Hal
**          Pointer to a variable that will hold the gcoHAL object pointer.
*/
gceSTATUS
gcoHAL_Construct(
    IN gctPOINTER Context,
    IN gcoOS Os,
    OUT gcoHAL * Hal
    )
{
    gctBOOL created = gcvFALSE;
    gcoHAL hal = gcPLS.hal;
    gceSTATUS status;
    gctPOINTER pointer = gcvNULL;
    gctBOOL separated3D = gcvFALSE;
    gctBOOL separated2D = gcvFALSE;
    gcsHAL_INTERFACE iface;
    gctINT32 i;

    gcmHEADER_ARG("Context=0x%x OS=0x%x", Context, Os);

    /* Verify the arguments. */
    gcmDEBUG_VERIFY_ARGUMENT(Hal != gcvNULL);

    if (hal == gcvNULL)
    {
        /* Create the gcoHAL object. */
        gcmONERROR(gcoOS_Allocate(gcvNULL,
                                  gcmSIZEOF(struct _gcoHAL),
                                  &pointer));
        hal     = pointer;
        created = gcvTRUE;

        gcoOS_ZeroMemory(hal, gcmSIZEOF(struct _gcoHAL));

        /* Initialize the object. */
        hal->object.type = gcvOBJ_HAL;

        /* Zero the gco2D, gco3D, and gcoDUMP objects. */
        hal->dump      = gcvNULL;
        hal->reference = gcvNULL;

        /* Initialize timeOut value */
        hal->timeOut     = gcdGPU_TIMEOUT;

        /* Query the kernel version number. */
        iface.command = gcvHAL_VERSION;
        gcmONERROR(gcoOS_DeviceControl(gcvNULL,
                                       IOCTL_GCHAL_INTERFACE,
                                       &iface, gcmSIZEOF(iface),
                                       &iface, gcmSIZEOF(iface)));

        /* Test if versions match. */
        if ((iface.u.Version.major != gcvVERSION_MAJOR)
        ||  (iface.u.Version.minor != gcvVERSION_MINOR)
        ||  (iface.u.Version.patch != gcvVERSION_PATCH)
        ||  (iface.u.Version.build != gcvVERSION_BUILD)
        )
        {
            gcmPRINT("HAL user version %d.%d.%d build %u %s %s",
                     gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH,
                     gcvVERSION_BUILD, gcvVERSION_DATE, gcvVERSION_TIME);
            gcmPRINT("HAL kernel version %d.%d.%d build %u",
                     iface.u.Version.major, iface.u.Version.minor,
                     iface.u.Version.patch, iface.u.Version.build);

            gcmONERROR(gcvSTATUS_VERSION_MISMATCH);
        }

#if gcmIS_DEBUG(gcdDEBUG_TRACE)
    gcmTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HAL,
                  "HAL user version %d.%d.%d build %u %s %s",
                  gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH,
                  gcvVERSION_BUILD, gcvVERSION_DATE, gcvVERSION_TIME);
    gcmTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HAL,
                  "HAL kernel version %d.%d.%d build %u",
                  iface.u.Version.major, iface.u.Version.minor,
                  iface.u.Version.patch, iface.u.Version.build);
#endif

        /* Query chip info */
        iface.command = gcvHAL_CHIP_INFO;
        gcmONERROR(gcoOS_DeviceControl(gcvNULL,
                                       IOCTL_GCHAL_INTERFACE,
                                       &iface, gcmSIZEOF(iface),
                                       &iface, gcmSIZEOF(iface)));

        hal->chipCount = iface.u.ChipInfo.count;

        for (i = 0; i < hal->chipCount; i++)
        {
            hal->chipTypes[i] = iface.u.ChipInfo.types[i];

            switch (hal->chipTypes[i])
            {
            case gcvHARDWARE_3D:
                separated3D = gcvTRUE;
                break;
            case gcvHARDWARE_2D:
                separated2D = gcvTRUE;
                break;
            default:
                break;
            }
        }

        hal->separated3D2D = (separated3D && separated2D);

#if VIVANTE_PROFILER
        hal->profiler.enable = 0;
#endif

        /* Create reference. */
        gcmONERROR(gcoOS_AtomConstruct(Os, &hal->reference));
    }
コード例 #13
0
/*******************************************************************************
**
**  gcoBUFFER_Commit
**
**  Commit the command buffer to the hardware.
**
**  INPUT:
**
**      gcoBUFFER Buffer
**          Pointer to a gcoBUFFER object.
**
**      gcePIPE_SELECT CurrentPipe
**          Current graphics pipe.
**
**      gcsSTATE_DELTA_PTR StateDelta
**          Pointer to the state delta.
**
**      gcoQUEUE Queue
**          Pointer to a gcoQUEUE object.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gcoBUFFER_Commit(
    IN gcoBUFFER Buffer,
    IN gcePIPE_SELECT CurrentPipe,
    IN gcsSTATE_DELTA_PTR StateDelta,
    IN gcoQUEUE Queue
    )
{
    gcsHAL_INTERFACE iface;
    gceSTATUS status;
    gcoCMDBUF current;

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

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Buffer, gcvOBJ_BUFFER);
    gcmVERIFY_OBJECT(Queue, gcvOBJ_QUEUE);

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

    if (current == gcvNULL)
    {
        /* No command buffer, done. */
        gcmFOOTER_NO();
        return gcvSTATUS_OK;
    }

    if (current->offset - current->startOffset <= Buffer->info.reservedHead)
    {
        /* Commit the event queue. */
        status = gcoQUEUE_Commit(Queue);
        gcmFOOTER();
        return status;
    }

    /* Make sure the tail got aligned properly. */
    current->offset = gcmALIGN(current->offset, Buffer->info.alignment);

    if (gcPLS.hal->dump != gcvNULL)
    {
        /* Dump the command buffer. */
        gcmVERIFY_OK(
            gcoDUMP_DumpData(gcPLS.hal->dump,
                             gcvTAG_COMMAND,
                             0,
                             current->offset
                             - current->startOffset
                             - Buffer->info.reservedHead,
                             (gctUINT8_PTR) current->logical
                             + current->startOffset
                             + Buffer->info.reservedHead));
    }

    /* The current pipe becomes the exit pipe for the current command buffer. */
    current->exitPipe = CurrentPipe;

    /* Send command and context buffer to hardware. */
    iface.command = gcvHAL_COMMIT;
    iface.u.Commit.context       =
#ifndef VIVANTE_NO_3D
        (current->using2D && !current->using3D) ? gcvNULL : Buffer->context;
#else
        gcvNULL;
#endif

    iface.u.Commit.commandBuffer = current;
    iface.u.Commit.delta         = StateDelta;
    iface.u.Commit.queue         = Queue->head;

    /* Call kernel service. */
    gcmONERROR(
        gcoOS_DeviceControl(gcvNULL,
                            IOCTL_GCHAL_INTERFACE,
                            &iface, gcmSIZEOF(iface),
                            &iface, gcmSIZEOF(iface)));

    gcmONERROR(iface.status);

    /* Free the event queue. */
    gcmONERROR(gcoQUEUE_Free(Queue));

    /* Advance the offset for next commit. */
    current->startOffset = current->offset + Buffer->info.reservedTail;

    if (current->bytes - current->startOffset > Buffer->totalReserved)
    {
        /* Adjust buffer offset and size. */
        current->offset = current->startOffset + Buffer->info.reservedHead;
        current->free   = current->bytes - current->offset
                        - Buffer->info.alignment
                        - Buffer->info.reservedTail;
    }
    else
    {
        /* Buffer is full. */
        current->startOffset = current->bytes;
        current->offset      = current->bytes;
        current->free        = 0;
    }

    /* The exit pipe becomes the entry pipe for the next command buffer. */
    current->entryPipe = current->exitPipe;

#if gcdSECURE_USER
    /* Reset the state array tail. */
    current->hintArrayTail = current->hintArray;
#endif

    /* Reset usage flags. */
    current->using2D         = gcvFALSE;
    current->using3D         = gcvFALSE;
    current->usingFilterBlit = gcvFALSE;
    current->usingPalette    = gcvFALSE;

    /* Success. */
    gcmFOOTER_NO();
    return gcvSTATUS_OK;

OnError:
    /* Return the status. */
    gcmFOOTER();
    return status;
}
コード例 #14
0
/*******************************************************************************
**
**  gckVIDMEM_ConstructVirtual
**
**  Construct a new gcuVIDMEM_NODE union for virtual memory.
**
**  INPUT:
**
**      gckKERNEL Kernel
**          Pointer to an gckKERNEL object.
**
**      gctSIZE_T Bytes
**          Number of byte to allocate.
**
**  OUTPUT:
**
**      gcuVIDMEM_NODE_PTR * Node
**          Pointer to a variable that receives the gcuVIDMEM_NODE union pointer.
*/
gceSTATUS
gckVIDMEM_ConstructVirtual(
    IN gckKERNEL Kernel,
    IN gctBOOL Contiguous,
    IN gctSIZE_T Bytes,
#ifdef __QNXNTO__
    IN gctHANDLE Handle,
#endif
    OUT gcuVIDMEM_NODE_PTR * Node
    )
{
    gckOS os;
    gceSTATUS status;
    gcuVIDMEM_NODE_PTR node = gcvNULL;

    gcmkHEADER_ARG("Kernel=0x%x Bytes=%lu", Kernel, Bytes);

    /* Verify the arguments. */
    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
    gcmkVERIFY_ARGUMENT(Bytes > 0);
    gcmkVERIFY_ARGUMENT(Node != gcvNULL);
#ifdef __QNXNTO__
    gcmkVERIFY_ARGUMENT(Handle != gcvNULL);
#endif

    /* Extract the gckOS object pointer. */
    os = Kernel->os;
    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);

    /* Allocate an gcuVIDMEM_NODE union. */
    gcmkONERROR(
        gckOS_Allocate(os, gcmSIZEOF(gcuVIDMEM_NODE), (gctPOINTER *) &node));

    /* Initialize gcuVIDMEM_NODE union for virtual memory. */
    node->Virtual.kernel        = Kernel;
    node->Virtual.contiguous    = Contiguous;
    node->Virtual.locked        = 0;
    node->Virtual.logical       = gcvNULL;
    node->Virtual.pageTable     = gcvNULL;
    node->Virtual.mutex         = gcvNULL;
#ifdef __QNXNTO__
    node->Virtual.next          = gcvNULL;
    node->Virtual.unlockPending = gcvFALSE;
    node->Virtual.freePending   = gcvFALSE;
    node->Virtual.handle        = Handle;
#else
    node->Virtual.pending       = gcvFALSE;
#endif

    /* Create the mutex. */
    gcmkONERROR(
        gckOS_CreateMutex(os, &node->Virtual.mutex));

    /* Allocate the virtual memory. */
    gcmkONERROR(
        gckOS_AllocatePagedMemoryEx(os,
                                    node->Virtual.contiguous,
                                    node->Virtual.bytes = Bytes,
                                    &node->Virtual.physical));

#ifdef __QNXNTO__
    /* Register. */
    gckMMU_InsertNode(Kernel->mmu, node);
#endif

    /* Return pointer to the gcuVIDMEM_NODE union. */
    *Node = node;

    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                   "Created virtual node 0x%x for %u bytes @ 0x%x",
                   node, Bytes, node->Virtual.physical);

    /* Success. */
    gcmkFOOTER_ARG("*Node=0x%x", *Node);
    return gcvSTATUS_OK;

OnError:
    /* Roll back. */
    if (node != gcvNULL)
    {
        if (node->Virtual.mutex != gcvNULL)
        {
            /* Destroy the mutex. */
            gcmkVERIFY_OK(gckOS_DeleteMutex(os, node->Virtual.mutex));
        }

        /* Free the structure. */
        gcmkVERIFY_OK(gckOS_Free(os, node));
    }

    /* Return the status. */
    gcmkFOOTER();
    return status;
}
コード例 #15
0
/*******************************************************************************
**
**  gckVIDMEM_Construct
**
**  Construct a new gckVIDMEM object.
**
**  INPUT:
**
**      gckOS Os
**          Pointer to an gckOS object.
**
**      gctUINT32 BaseAddress
**          Base address for the video memory heap.
**
**      gctSIZE_T Bytes
**          Number of bytes in the video memory heap.
**
**      gctSIZE_T Threshold
**          Minimum number of bytes beyond am allocation before the node is
**          split.  Can be used as a minimum alignment requirement.
**
**      gctSIZE_T BankSize
**          Number of bytes per physical memory bank.  Used by bank
**          optimization.
**
**  OUTPUT:
**
**      gckVIDMEM * Memory
**          Pointer to a variable that will hold the pointer to the gckVIDMEM
**          object.
*/
gceSTATUS
gckVIDMEM_Construct(
    IN gckOS Os,
    IN gctUINT32 BaseAddress,
    IN gctSIZE_T Bytes,
    IN gctSIZE_T Threshold,
    IN gctSIZE_T BankSize,
    OUT gckVIDMEM * Memory
    )
{
    gckVIDMEM memory = gcvNULL;
    gceSTATUS status;
    gcuVIDMEM_NODE_PTR node;
    gctINT i, banks = 0;

    gcmkHEADER_ARG("Os=0x%x BaseAddress=%08x Bytes=%lu Threshold=%lu "
                   "BankSize=%lu",
                   Os, BaseAddress, Bytes, Threshold, BankSize);

    /* Verify the arguments. */
    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
    gcmkVERIFY_ARGUMENT(Bytes > 0);
    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);

    /* Allocate the gckVIDMEM object. */
    gcmkONERROR(
        gckOS_Allocate(Os,
                       gcmSIZEOF(struct _gckVIDMEM),
                       (gctPOINTER *) &memory));

    /* Initialize the gckVIDMEM object. */
    memory->object.type = gcvOBJ_VIDMEM;
    memory->os          = Os;

    /* Set video memory heap information. */
    memory->baseAddress = BaseAddress;
    memory->bytes       = Bytes;
    memory->freeBytes   = Bytes;
    memory->threshold   = Threshold;
    memory->mutex       = gcvNULL;

    BaseAddress = 0;

    /* Walk all possible banks. */
    for (i = 0; i < gcmCOUNTOF(memory->sentinel); ++i)
    {
        gctSIZE_T bytes;

        if (BankSize == 0)
        {
            /* Use all bytes for the first bank. */
            bytes = Bytes;
        }
        else
        {
            /* Compute number of bytes for this bank. */
            bytes = gcmALIGN(BaseAddress + 1, BankSize) - BaseAddress;

            if (bytes > Bytes)
            {
                /* Make sure we don't exceed the total number of bytes. */
                bytes = Bytes;
            }
        }

        if (bytes == 0)
        {
            /* Mark heap is not used. */
            memory->sentinel[i].VidMem.next     =
            memory->sentinel[i].VidMem.prev     =
            memory->sentinel[i].VidMem.nextFree =
            memory->sentinel[i].VidMem.prevFree = gcvNULL;
            continue;
        }

        /* Allocate one gcuVIDMEM_NODE union. */
        gcmkONERROR(
            gckOS_Allocate(Os,
                           gcmSIZEOF(gcuVIDMEM_NODE),
                           (gctPOINTER *) &node));

        /* Initialize gcuVIDMEM_NODE union. */
        node->VidMem.memory    = memory;

        node->VidMem.next      =
        node->VidMem.prev      =
        node->VidMem.nextFree  =
        node->VidMem.prevFree  = &memory->sentinel[i];

        node->VidMem.offset    = BaseAddress;
        node->VidMem.bytes     = bytes;
        node->VidMem.alignment = 0;
        node->VidMem.physical  = 0;
        node->VidMem.pool      = gcvPOOL_UNKNOWN;

        node->VidMem.locked    = 0;

#ifdef __QNXNTO__
        node->VidMem.logical   = gcvNULL;
        node->VidMem.handle    = 0;
#endif

        /* Initialize the linked list of nodes. */
        memory->sentinel[i].VidMem.next     =
        memory->sentinel[i].VidMem.prev     =
        memory->sentinel[i].VidMem.nextFree =
        memory->sentinel[i].VidMem.prevFree = node;

        /* Mark sentinel. */
        memory->sentinel[i].VidMem.bytes = 0;

        /* Adjust address for next bank. */
        BaseAddress += bytes;
        Bytes       -= bytes;
        banks       ++;
    }

    /* Assign all the bank mappings. */
    memory->mapping[gcvSURF_RENDER_TARGET]      = banks - 1;
    memory->mapping[gcvSURF_BITMAP]             = banks - 1;
    if (banks > 1) --banks;
    memory->mapping[gcvSURF_DEPTH]              = banks - 1;
    memory->mapping[gcvSURF_HIERARCHICAL_DEPTH] = banks - 1;
    if (banks > 1) --banks;
    memory->mapping[gcvSURF_TEXTURE]            = banks - 1;
    if (banks > 1) --banks;
    memory->mapping[gcvSURF_VERTEX]             = banks - 1;
    if (banks > 1) --banks;
    memory->mapping[gcvSURF_INDEX]              = banks - 1;
    if (banks > 1) --banks;
    memory->mapping[gcvSURF_TILE_STATUS]        = banks - 1;
    if (banks > 1) --banks;
    memory->mapping[gcvSURF_TYPE_UNKNOWN]       = 0;

    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                  "[GALCORE] INDEX:         bank %d",
                  memory->mapping[gcvSURF_INDEX]);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                  "[GALCORE] VERTEX:        bank %d",
                  memory->mapping[gcvSURF_VERTEX]);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                  "[GALCORE] TEXTURE:       bank %d",
                  memory->mapping[gcvSURF_TEXTURE]);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                  "[GALCORE] RENDER_TARGET: bank %d",
                  memory->mapping[gcvSURF_RENDER_TARGET]);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                  "[GALCORE] DEPTH:         bank %d",
                  memory->mapping[gcvSURF_DEPTH]);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                  "[GALCORE] TILE_STATUS:   bank %d",
                  memory->mapping[gcvSURF_TILE_STATUS]);

    /* Allocate the mutex. */
    gcmkONERROR(gckOS_CreateMutex(Os, &memory->mutex));

    /* Return pointer to the gckVIDMEM object. */
    *Memory = memory;

    /* Success. */
    gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
    return gcvSTATUS_OK;

OnError:
    /* Roll back. */
    if (memory != gcvNULL)
    {
        if (memory->mutex != gcvNULL)
        {
            /* Delete the mutex. */
            gcmkVERIFY_OK(gckOS_DeleteMutex(Os, memory->mutex));
        }

        for (i = 0; i < banks; ++i)
        {
            /* Free the heap. */
            gcmkASSERT(memory->sentinel[i].VidMem.next != gcvNULL);
            gcmkVERIFY_OK(gckOS_Free(Os, memory->sentinel[i].VidMem.next));
        }

        /* Free the object. */
        gcmkVERIFY_OK(gckOS_Free(Os, memory));
    }

    /* Return the status. */
    gcmkFOOTER();
    return status;
}
コード例 #16
0
/*******************************************************************************
**  gckKERNEL_NewRecord
**
**  Create a new database record structure and insert it to the head of the
**  database.
**
**  INPUT:
**
**      gckKERNEL Kernel
**          Pointer to a gckKERNEL object.
**
**      gcsDATABASE_PTR Database
**          Pointer to a database structure.
**
**  OUTPUT:
**
**      gcsDATABASE_RECORD_PTR * Record
**          Pointer to a variable receiving the database record structure
**          pointer on success.
*/
static gceSTATUS
gckKERNEL_NewRecord(
    IN gckKERNEL Kernel,
    IN gcsDATABASE_PTR Database,
    IN gctUINT32 Slot,
    OUT gcsDATABASE_RECORD_PTR * Record
    )
{
    gceSTATUS status;
    gctBOOL acquired = gcvFALSE;
    gcsDATABASE_RECORD_PTR record = gcvNULL;

    gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel, Database);

    /* Acquire the database mutex. */
    gcmkONERROR(
        gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
    acquired = gcvTRUE;

    if (Kernel->db->freeRecord != gcvNULL)
    {
        /* Allocate the record from the free list. */
        record             = Kernel->db->freeRecord;
        Kernel->db->freeRecord = record->next;
    }
    else
    {
        gctPOINTER pointer = gcvNULL;

        /* Allocate the record from the heap. */
        gcmkONERROR(gckOS_Allocate(Kernel->os,
                                   gcmSIZEOF(gcsDATABASE_RECORD),
                                   &pointer));

        record = pointer;
    }

    /* Insert the record in the database. */
    record->next         = Database->list[Slot];
    Database->list[Slot] = record;

    /* Release the database mutex. */
    gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));

    /* Return the record. */
    *Record = record;

    /* Success. */
    gcmkFOOTER_ARG("*Record=0x%x", *Record);
    return gcvSTATUS_OK;

OnError:
    if (acquired)
    {
        /* Release the database mutex. */
        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
    }
    if (record != gcvNULL)
    {
        gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, record));
    }

    /* Return the status. */
    gcmkFOOTER();
    return status;
}
コード例 #17
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;
}
コード例 #18
0
int
main(
    int argc,
    char * argv[]
    )
{
    gctBOOL         dumpLog      = gcvFALSE;
    gctSTRING       fileName[2]  = { gcvNULL, gcvNULL };
    gcSHADER        shaders[2]   = { gcvNULL, gcvNULL };
    gctINT          i;
    gcoOS           os           = gcvNULL;
    gcoHAL          hal          = gcvNULL;
    gceSTATUS       result;
    gctUINT         option       = 1;   /* no optimization */
    char            outFile[128] = { '\0' };
    char            logVSFile[128] = { '\0' };
    char            logFSFile[128] = { '\0' };

    printf("vCompile version 0.8, Copyright (c) 2005-2011, Vivante Corporation\n\n");

#ifdef _WIN32
    _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) /*| _CRTDBG_CHECK_ALWAYS_DF*/ | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );
    /* _CrtSetBreakAlloc(79); */
#endif

#if gcdDEBUG
    gcoOS_SetDebugLevel(gcvLEVEL_VERBOSE);
    gcoOS_SetDebugZone(gcvZONE_COMPILER);
#endif

    for (i = 1; i < argc; i++)
    {
        if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-l")))
        {
            dumpLog = gcvTRUE;
        }
        else if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-O0")))
        {
            /* Currently, optimization level is either FULL or NONE */
            option = 0;     /* no optimization */
        }
        else if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-O")))
        {
            option = 1;     /* full optimization */
        }
        else if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-OT")))
        {
            /* For optimization unit test */
            if (i++ == argc)
            {
                printf("*ERROR* Optimization testing pattern not provided.\n");
                return 1;
            }
            else
            {
                gctINT testPattern;

                gcmVERIFY_OK(gcoOS_StrToInt(argv[i], (gctINT *)&testPattern));
                if (testPattern < 0)
                {
                    printf("*ERROR* Unknown optimization testing pattern.\n");
                    return 1;
                }
                option = testPattern;
            }
        }
        else
        {
            if (fileName[0] == gcvNULL) fileName[0] = argv[i];
            else if (fileName[1] == gcvNULL) fileName[1] = argv[i];
            else
            {
                printf("*ERROR* Too many shaders.\n");
                return 1;
            }
        }
    }

    if (fileName[0] == gcvNULL)
    {
        printf("Usage: %s [-l] [-O0] shaderFileName [shaderFileName]\n", argv[0]);
        printf("  -l   Generate log file.\n"
               "  -O0  Disable optimizations.\n"
               "\n"
               "If only one shader is specified, that shader will be compiled into a .gcSL\n"
               "file.  If two shaders are specified, those shaders will be compiled and\n"
               "linked into a .gcPGM file. With two shaders, the vertex shader file needs\n"
               "to be the first.\n");
        return 0;
    }

    result = gcoOS_Construct(gcvNULL, &os);
    if (result != gcvSTATUS_OK)
    {
        printf("*ERROR* Failed to construct a new gcoOS object\n");
        return 1;
    }

    result = gcoHAL_Construct(gcvNULL, os, &hal);
    if (result != gcvSTATUS_OK)
    {
        printf("*ERROR* Failed to construct a new gcoHAL object\n");
        goto ErrorExit;
    }

    /* Dump compile log only when one shader is present */
    shaders[0] = CompileFile(os, fileName[0], hal, option, dumpLog && (fileName[1] == gcvNULL), fileName[1] == gcvNULL );

    if (shaders[0] == gcvNULL)
    {
        goto ErrorExit;
    }

    if (fileName[1] != gcvNULL)
    {
        gctSIZE_T programBufferSize = 0;
        gctPOINTER programBuffer = gcvNULL;
        gcsHINT_PTR hints = gcvNULL;
        gceSTATUS status;
        gctPOINTER binary = gcvNULL;
        gctSIZE_T binarySize = 0;
        FILE * f;
        gctSTRING p;

        gcoOS_StrCopySafe(outFile, gcmSIZEOF(outFile), fileName[0]);
        p = strrchr(outFile, '.');
        gcoOS_StrCopySafe(p, gcmSIZEOF(outFile) - (p - outFile), ".gcPGM");

        gcoOS_StrCopySafe(logVSFile, gcmSIZEOF(logVSFile), fileName[0]);
        gcoOS_StrCatSafe(logVSFile, gcmSIZEOF(logVSFile), ".log");

        gcoOS_StrCopySafe(logFSFile, gcmSIZEOF(logFSFile), fileName[1]);
        gcoOS_StrCatSafe(logFSFile, gcmSIZEOF(logFSFile), ".log");

        shaders[1] = CompileFile(os, fileName[1], hal, option, gcvFALSE, gcvFALSE);
        if (shaders[1] == gcvNULL)
        {
            goto ErrorExit;
        }

        if ( dumpLog)
        {
            gcoOS_SetDebugShaderFiles(logVSFile, logFSFile);
        }
        status = gcLinkShaders(shaders[0],
                               shaders[1],
                               gcvSHADER_DEAD_CODE
                               | gcvSHADER_RESOURCE_USAGE
                               | gcvSHADER_OPTIMIZER
                               | gcvSHADER_USE_GL_Z
                               | gcvSHADER_USE_GL_POSITION
                               | gcvSHADER_USE_GL_FACE,
                               &programBufferSize,
                               &programBuffer,
                               &hints);
        if ( dumpLog)
        {
            gcoOS_SetDebugShaderFiles(gcvNULL, gcvNULL);
        }

        if (gcmIS_ERROR(status))
        {
            printf("*ERROR* gcLinkShaders returned errror %d\n", status);
        }
        else
        {
            int ret;
            status = gcSaveProgram(shaders[0],
                                   shaders[1],
                                   programBufferSize,
                                   programBuffer,
                                   hints,
                                   &binary,
                                   &binarySize);

            if (gcmIS_ERROR(status))
            {
                printf("*ERROR* gcSaveShaders returned errror %d\n", status);
            }

            f = fopen(outFile, "wb");
            ret = fwrite(binary, binarySize, 1, f);
            if (ret);
            fclose(f);
        }

        if (programBuffer != gcvNULL) gcoOS_Free(os, programBuffer);
        if (hints         != gcvNULL) gcoOS_Free(os, hints);
        if (binary        != gcvNULL) gcoOS_Free(os, binary);
    }

    gcSHADER_Destroy(shaders[0]);
    if (shaders[1] != gcvNULL) gcSHADER_Destroy(shaders[1]);
    gcoHAL_Destroy(hal);
    gcoOS_Destroy(os);
    return 0;

ErrorExit:
    if (shaders[0] != gcvNULL) gcSHADER_Destroy(shaders[0]);
    if (shaders[1] != gcvNULL) gcSHADER_Destroy(shaders[1]);
    if (gcvNULL != hal) gcoHAL_Destroy(hal);
    if (gcvNULL != os) gcoOS_Destroy(os);

    return 1;
}
コード例 #19
0
static gceSTATUS
_CompactKernelHeap(
    IN gckHEAP Heap
    )
{
    gcskHEAP_PTR heap, next;
    gctPOINTER p;
    gcskHEAP_PTR freeList = gcvNULL;

    gcmkHEADER_ARG("Heap=0x%x", Heap);

    /* Walk all the heaps. */
    for (heap = Heap->heap; heap != gcvNULL; heap = next)
    {
        gcskNODE_PTR lastFree = gcvNULL;

        /* Zero out the free list. */
        heap->freeList = gcvNULL;

        /* Start at the first node. */
        for (p = (gctUINT8_PTR) (heap + 1);;)
        {
            /* Convert the pointer. */
            gcskNODE_PTR node = (gcskNODE_PTR) p;

            gcmkASSERT(p <= (gctPOINTER) ((gctUINT8_PTR) (heap + 1) + heap->size));

            /* Test if this node not used. */
            if (node->next != gcdIN_USE)
            {
                /* Test if this is the end of the heap. */
                if (node->bytes == 0)
                {
                    break;
                }

                /* Test of this is the first free node. */
                else if (lastFree == gcvNULL)
                {
                    /* Initialzie the free list. */
                    heap->freeList = node;
                    lastFree       = node;
                }

                else
                {
                    /* Test if this free node is contiguous with the previous
                    ** free node. */
                    if ((gctUINT8_PTR) lastFree + lastFree->bytes == p)
                    {
                        /* Just increase the size of the previous free node. */
                        lastFree->bytes += node->bytes;
                    }
                    else
                    {
                        /* Add to linked list. */
                        lastFree->next = node;
                        lastFree       = node;
                    }
                }
            }

            /* Move to next node. */
            p = (gctUINT8_PTR) node + node->bytes;
        }

        /* Mark the end of the chain. */
        if (lastFree != gcvNULL)
        {
            lastFree->next = gcvNULL;
        }

        /* Get next heap. */
        next = heap->next;

        /* Check if the entire heap is free. */
        if ((heap->freeList != gcvNULL)
        &&  (heap->freeList->bytes == heap->size - gcmSIZEOF(gcskNODE))
        )
        {
            /* Remove the heap from the linked list. */
            if (heap->prev == gcvNULL)
            {
                Heap->heap = next;
            }
            else
            {
                heap->prev->next = next;
            }

            if (heap->next != gcvNULL)
            {
                heap->next->prev = heap->prev;
            }

#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
            /* Update profiling. */
            Heap->heapCount  -= 1;
            Heap->heapMemory -= heap->size + gcmSIZEOF(gcskHEAP);
#endif

            /* Add this heap to the list of heaps that need to be freed. */
            heap->next = freeList;
            freeList   = heap;
        }
    }

    if (freeList != gcvNULL)
    {
        /* Release the mutex, remove any chance for a dead lock. */
        gcmkVERIFY_OK(
            gckOS_ReleaseMutex(Heap->os, Heap->mutex));

        /* Free all heaps in the free list. */
        for (heap = freeList; heap != gcvNULL; heap = next)
        {
            /* Get pointer to the next heap. */
            next = heap->next;

            /* Free the heap. */
            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
                           "Freeing heap 0x%x (%lu bytes)",
                           heap, heap->size + gcmSIZEOF(gcskHEAP));
            gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
        }

        /* Acquire the mutex again. */
        gcmkVERIFY_OK(
            gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
    }

    /* Success. */
    gcmkFOOTER_NO();
    return gcvSTATUS_OK;
}
コード例 #20
0
gceSTATUS
gcoQUEUE_AppendEvent(
    IN gcoQUEUE Queue,
    IN gcsHAL_INTERFACE * Interface
    )
{
    gceSTATUS status;
    gcsQUEUE_PTR record = gcvNULL;
#ifdef __QNXNTO__
    gctSIZE_T allocationSize;
    gctPHYS_ADDR physAddr;
#else
    gctPOINTER pointer = gcvNULL;
#endif

    gcmHEADER_ARG("Queue=0x%x Interface=0x%x", Queue, Interface);

    /* Verify the arguments. */
    gcmVERIFY_OBJECT(Queue, gcvOBJ_QUEUE);
    gcmVERIFY_ARGUMENT(Interface != gcvNULL);

    /* Allocate record. */
#ifdef __QNXNTO__
    allocationSize = gcmSIZEOF(gcsQUEUE);
    if (Queue->freeBytes < allocationSize)
    {
        gctSIZE_T recordsSize = BUFFER_SIZE;
        gcsQUEUE_PTR prevRecords = Queue->records;
        gcsHAL_INTERFACE iface;

        /* Allocate new set of records. */
        gcmONERROR(
            gcoOS_AllocateNonPagedMemory(gcvNULL,
                                         gcvTRUE,
                                         &recordsSize,
                                         &physAddr,
                                         (gctPOINTER *) &Queue->records));
        Queue->freeBytes = recordsSize;
        Queue->offset = 0;

        if ( Queue->freeBytes < allocationSize )
        {
            gcmFOOTER_ARG("status=%d", gcvSTATUS_DATA_TOO_LARGE);
            return gcvSTATUS_DATA_TOO_LARGE;
        }

        /* Schedule to free Queue->records,
         * hence not unmapping currently scheduled events immediately. */
        iface.command = gcvHAL_FREE_NON_PAGED_MEMORY;
        iface.u.FreeNonPagedMemory.bytes = BUFFER_SIZE;
        iface.u.FreeNonPagedMemory.physical = 0;
        iface.u.FreeNonPagedMemory.logical = prevRecords;

        gcmONERROR(
            gcoQUEUE_AppendEvent(Queue, &iface));
    }

    record = (gcsQUEUE_PTR)((gctUINT32)Queue->records + Queue->offset);
    Queue->offset += allocationSize;
    Queue->freeBytes -= allocationSize;
#else
    /* Check if we have records on the free list. */
    if (Queue->freeList != gcvNULL)
    {
        /* Allocate from hte free list. */
        record          = Queue->freeList;
        Queue->freeList = record->next;
    }
    else
    {
        gcmONERROR(gcoOS_Allocate(gcvNULL,
                       gcmSIZEOF(gcsQUEUE),
                                  &pointer));
        record = pointer;
    }
#endif

    /* Initialize record. */
    record->next  = gcvNULL;
    gcoOS_MemCopy(&record->iface, Interface, gcmSIZEOF(record->iface));

    if (Queue->head == gcvNULL)
    {
        /* Initialize queue. */
        Queue->head = record;
    }
    else
    {
        /* Append record to end of queue. */
        Queue->tail->next = record;
    }

    /* Mark end of queue. */
    Queue->tail = record;

    /* update count */
    Queue->recordCount++;

    /* Success. */
    gcmFOOTER_NO();
    return gcvSTATUS_OK;

OnError:
#ifndef __QNXNTO__
    if (pointer != gcvNULL)
    {
        /* Put record on free list. */
        record->next    = Queue->freeList;
        Queue->freeList = record;
    }
#endif

    /* Return the status. */
    gcmFOOTER();
    return status;
}
コード例 #21
0
static ssize_t gc_proc_write(
    struct file *file,
    const char *buff,
    size_t len,
    loff_t *off)
{
    char messages[256];

    if(len > 256)
        len = 256;

    if(copy_from_user(messages, buff, len))
        return -EFAULT;

    printk("\n");
    if(strncmp(messages, "dutycycle", 9) == 0)
    {
        gctINT32            option;
        gcuDATABASE_INFO    gpuIdle;
        static gctUINT64    startTime = 0;
        static gctUINT64    endTime = 0;

        gcmkVERIFY_OK(gckOS_ZeroMemory((gctPOINTER)&gpuIdle, gcmSIZEOF(gcuDATABASE_INFO)));

        sscanf(messages+9, "%d", &option);

        switch(option) {
        case 0:
            gcmkVERIFY_OK(gckOS_GetProfileTick(&startTime));
            gcmkVERIFY_OK(gckKERNEL_QueryDutyCycleDB(galDevice->kernels[gcvCORE_MAJOR], gcvTRUE, &gpuIdle));
            gpuIdle.time = 0;
            endTime = 0;
            break;
        case 1:
            gcmkVERIFY_OK(gckKERNEL_QueryDutyCycleDB(galDevice->kernels[gcvCORE_MAJOR], gcvFALSE, &gpuIdle));
            gcmkVERIFY_OK(gckOS_GetProfileTick(&endTime));
            break;
        default:
            printk(KERN_INFO "usage: echo dutycycle [0|1] > /proc/driver/gc\n");
        }

        if(startTime != 0 && endTime != 0)
        {
            gctUINT64   delta = endTime - startTime;
            gctUINT32   per   = 100 - 100 * gckOS_ProfileToMS(gpuIdle.time) / gckOS_ProfileToMS(delta);
            printk(KERN_INFO "\n  %%GPU     START       END     DELTA      IDLE\n");
            printk(KERN_INFO "%5u%%  %8u  %8u  %8u  %8u\n\n",
                per,
                gckOS_ProfileToMS(startTime),
                gckOS_ProfileToMS(endTime),
                gckOS_ProfileToMS(delta),
                gckOS_ProfileToMS(gpuIdle.time));
        }
    }
    else if(strncmp(messages, "reg", 3) == 0)
    {
        gctINT32 option;
        gctUINT32 idle, address, clockControl;

        sscanf(messages+3, "%d", &option);

        switch(option) {
        case 1:
            /* Read the current FE address. */
            gckOS_ReadRegisterEx(galDevice->os,
                                 galDevice->kernels[0]->hardware->core,
                                 0x00664,
                                 &address);
            gcmkPRINT("address: 0x%2x\n", address);
            break;
        case 2:
            /* Read idle register. */
            gckOS_ReadRegisterEx(galDevice->os,
                                 galDevice->kernels[0]->hardware->core,
                                 0x00004,
                                 &idle);
            gcmkPRINT("idle: 0x%2x\n", idle);
            break;
        case 3:
            gckOS_ReadRegisterEx(galDevice->os,
                                 gcvCORE_MAJOR,
                                 0x00000,
                                 &clockControl);
            gcmkPRINT("clockControl: 0x%2x\n", clockControl);
            break;
        default:
            printk(KERN_INFO "usage: echo reg [1|2|3] > /proc/driver/gc\n");
        }
    }
    else if(strncmp(messages, "help", 4) == 0)
    {
        printk("Supported options:\n"
                "dutycycle       measure dutycycle in a period\n"
                "reg             enable debugging for register reading\n"
                "help            show this help page\n"
                "\n");
    }
    else
    {
        gcmkPRINT("unknown echo\n");
    }
    printk("\n");

    return len;
}
コード例 #22
0
/*******************************************************************************
**
**	gckCOMMAND_Commit
**
**	Commit a command buffer to the command queue.
**
**	INPUT:
**
**		gckCOMMAND Command
**			Pointer to an gckCOMMAND object.
**
**		gcoCMDBUF CommandBuffer
**			Pointer to an gcoCMDBUF object.
**
**		gcoCONTEXT Context
**			Pointer to an gcoCONTEXT object.
**
**	OUTPUT:
**
**		Nothing.
*/
gceSTATUS
gckCOMMAND_Commit(
    IN gckCOMMAND Command,
    IN gcoCMDBUF CommandBuffer,
    IN gcoCONTEXT Context,
    IN gctHANDLE Process
    )
{
    gcoCMDBUF commandBuffer;
    gcoCONTEXT context;
	gckHARDWARE hardware;
	gceSTATUS status;
	gctPOINTER initialLink, link;
	gctSIZE_T bytes, initialSize, lastRun;
	gcoCMDBUF buffer;
	gctPOINTER wait;
	gctSIZE_T waitSize;
	gctUINT32 offset;
	gctPOINTER fetchAddress;
	gctSIZE_T fetchSize;
	gctUINT8_PTR logical;
	gcsMAPPED_PTR stack = gcvNULL;
	gctINT acquired = 0;
#if gcdSECURE_USER
	gctUINT32_PTR hint;
#endif
#if gcdDUMP_COMMAND
    gctPOINTER dataPointer;
    gctSIZE_T dataBytes;
#endif
    gctPOINTER flushPointer;
    gctSIZE_T flushSize;

	gcmkHEADER_ARG("Command=0x%x CommandBuffer=0x%x Context=0x%x",
				   Command, CommandBuffer, Context);

	/* Verify the arguments. */
	gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);

#if gcdNULL_DRIVER == 2
	/* Do nothing with infinite hardware. */
	gcmkFOOTER_NO();
	return gcvSTATUS_OK;
#endif

	gcmkONERROR(
		_AddMap(Command->os,
				CommandBuffer,
				gcmSIZEOF(struct _gcoCMDBUF),
				(gctPOINTER *) &commandBuffer,
				&stack));
	gcmkVERIFY_OBJECT(commandBuffer, gcvOBJ_COMMANDBUFFER);
	gcmkONERROR(
		_AddMap(Command->os,
				Context,
				gcmSIZEOF(struct _gcoCONTEXT),
				(gctPOINTER *) &context,
				&stack));
	gcmkVERIFY_OBJECT(context, gcvOBJ_CONTEXT);

	/* Extract the gckHARDWARE and gckEVENT objects. */
	hardware = Command->kernel->hardware;
	gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);

	/* Acquire the context switching mutex. */
	gcmkONERROR(
		gckOS_AcquireMutex(Command->os,
						   Command->mutexContext,
						   gcvINFINITE));

	++acquired;

	/* Reserved slot in the context or command buffer. */
	gcmkONERROR(
		gckHARDWARE_PipeSelect(hardware, gcvNULL, 0, &bytes));

	/* Test if we need to switch to this context. */
	if ((context->id != 0)
	&&  (context->id != Command->currentContext)
	)
	{
		/* Map the context buffer.*/
		gcmkONERROR(
			_AddMap(Command->os,
					context->logical,
					context->bufferSize,
					(gctPOINTER *) &logical,
					&stack));

#if gcdSECURE_USER
		/* Map the hint array.*/
		gcmkONERROR(
			_AddMap(Command->os,
					context->hintArray,
					context->hintCount * gcmSIZEOF(gctUINT32),
					(gctPOINTER *) &hint,
					&stack));

        /* Loop while we have valid hints. */
        while (*hint != 0)
        {
            /* Map handle into physical address. */
            gcmkONERROR(
                gckKERNEL_MapLogicalToPhysical(
                    Command->kernel,
                    Process,
                    (gctPOINTER *) (logical + *hint)));

			/* Next hint. */
			++hint;
		}
#endif

		/* See if we have to check pipes. */
		if (context->pipe2DIndex != 0)
		{
			/* See if we are in the correct pipe. */
			if (context->initialPipe == Command->pipeSelect)
			{
				gctUINT32 reserved = bytes;
				gctUINT8_PTR nop   = logical;

				/* Already in the correct pipe, fill context buffer with NOP. */
				while (reserved > 0)
				{
					bytes = reserved;
					gcmkONERROR(
						gckHARDWARE_Nop(hardware, nop, &bytes));

					gcmkASSERT(reserved >= bytes);
					reserved -= bytes;
					nop      += bytes;
				}
			}
			else
			{
				/* Switch to the correct pipe. */
				gcmkONERROR(
					gckHARDWARE_PipeSelect(hardware,
										   logical,
										   context->initialPipe,
										   &bytes));
			}
		}

		/* Save initial link pointer. */
        initialLink = logical;
		initialSize = context->bufferSize;
        
#if MRVL_PRINT_CMD_BUFFER
		_AddCmdBuffer(
			Command, initialLink, initialSize, gcvTRUE, gcvFALSE
			);
#endif

        /* Save initial buffer to flush. */
        flushPointer = initialLink;
        flushSize    = initialSize;

        /* Save pointer to next link. */
        gcmkONERROR(
            _AddMap(Command->os,
                    context->link,
                    8,
                    &link,
                    &stack));

		/* Start parsing CommandBuffer. */
		buffer = commandBuffer;

		/* Mark context buffer as used. */
		if (context->inUse != gcvNULL)
		{
			gctBOOL_PTR inUse;

			gcmkONERROR(
				_AddMap(Command->os,
						(gctPOINTER) context->inUse,
						gcmSIZEOF(gctBOOL),
						(gctPOINTER *) &inUse,
						&stack));

			*inUse = gcvTRUE;
		}
	}

	else
	{
		/* Test if this is a new context. */
		if (context->id == 0)
		{
			/* Generate unique ID for the context buffer. */
			context->id = ++ Command->contextCounter;

			if (context->id == 0)
			{
				/* Context counter overflow (wow!) */
				gcmkONERROR(gcvSTATUS_TOO_COMPLEX);
			}
		}

		/* Map the command buffer. */
		gcmkONERROR(
			_AddMap(Command->os,
					commandBuffer->logical,
					commandBuffer->offset,
					(gctPOINTER *) &logical,
					&stack));

#if gcdSECURE_USER
		/* Map the hint table. */
		gcmkONERROR(
			_AddMap(Command->os,
					commandBuffer->hintCommit,
					commandBuffer->offset - commandBuffer->startOffset,
					(gctPOINTER *) &hint,
					&stack));

        /* Walk while we have valid hints. */
        while (*hint != 0)
        {
            /* Map the handle to a physical address. */
            gcmkONERROR(
                gckKERNEL_MapLogicalToPhysical(
                    Command->kernel,
                    Process,
                    (gctPOINTER *) (logical + *hint)));

			/* Next hint. */
			++hint;
		}
#endif

		if (context->entryPipe == Command->pipeSelect)
		{
			gctUINT32 reserved = Command->reservedHead;
			gctUINT8_PTR nop   = logical + commandBuffer->startOffset;

			/* Already in the correct pipe, fill context buffer with NOP. */
			while (reserved > 0)
			{
				bytes = reserved;
				gcmkONERROR(
					gckHARDWARE_Nop(hardware, nop, &bytes));

				gcmkASSERT(reserved >= bytes);
				reserved -= bytes;
				nop      += bytes;
			}
		}
		else
		{
			/* Switch to the correct pipe. */
			gcmkONERROR(
				gckHARDWARE_PipeSelect(hardware,
									   logical + commandBuffer->startOffset,
									   context->entryPipe,
									   &bytes));
		}

		/* Save initial link pointer. */
        initialLink = logical + commandBuffer->startOffset;
		initialSize = commandBuffer->offset
					- commandBuffer->startOffset
					+ Command->reservedTail;
        
#if MRVL_PRINT_CMD_BUFFER
		_AddCmdBuffer(
			Command, initialLink, initialSize, gcvFALSE, gcvFALSE
			);
#endif

        /* Save initial buffer to flush. */
        flushPointer = initialLink;
        flushSize    = initialSize;

        /* Save pointer to next link. */
        link = logical + commandBuffer->offset;

		/* No more data. */
		buffer = gcvNULL;
	}

#if MRVL_PRINT_CMD_BUFFER
	_AddLink(Command, Command->wait, initialLink);
#endif

#if gcdDUMP_COMMAND
    dataPointer = initialLink;
    dataBytes   = initialSize;
#endif

	/* Loop through all remaining command buffers. */
	if (buffer != gcvNULL)
	{
		/* Map the command buffer. */
		gcmkONERROR(
			_AddMap(Command->os,
					buffer->logical,
					buffer->offset + Command->reservedTail,
					(gctPOINTER *) &logical,
					&stack));
#if MRVL_PRINT_CMD_BUFFER
		_AddCmdBuffer(
			Command, (gctUINT32_PTR)logical, buffer->offset + Command->reservedTail, gcvFALSE, gcvFALSE
			);
#endif

#if gcdSECURE_USER
		/* Map the hint table. */
		gcmkONERROR(
			_AddMap(Command->os,
					buffer->hintCommit,
					buffer->offset - buffer->startOffset,
					(gctPOINTER *) &hint,
					&stack));

        /* Walk while we have valid hints. */
        while (*hint != 0)
        {
            /* Map the handle to a physical address. */
            gcmkONERROR(
                gckKERNEL_MapLogicalToPhysical(
                    Command->kernel,
                    Process,
                    (gctPOINTER *) (logical + *hint)));

			/* Next hint. */
			++hint;
		}
#endif

		/* First slot becomes a NOP. */
		{
			gctUINT32 reserved = Command->reservedHead;
			gctUINT8_PTR nop   = logical + buffer->startOffset;

			/* Already in the correct pipe, fill context buffer with NOP. */
			while (reserved > 0)
			{
				bytes = reserved;
				gcmkONERROR(
					gckHARDWARE_Nop(hardware, nop, &bytes));

				gcmkASSERT(reserved >= bytes);
				reserved -= bytes;
				nop      += bytes;
			}
		}

		/* Generate the LINK to this command buffer. */
		gcmkONERROR(
			gckHARDWARE_Link(hardware,
							 link,
                             logical + buffer->startOffset,
							 buffer->offset
							 - buffer->startOffset
							 + Command->reservedTail,
							 &bytes));
#if MRVL_PRINT_CMD_BUFFER
	_AddLink(Command, link, (gctUINT32_PTR)logical);
#endif

        /* Flush the initial buffer. */
        gcmkONERROR(gckOS_CacheFlush(Command->os,
                                     Process,
                                     flushPointer,
                                     flushSize));

        /* Save new flush pointer. */
        flushPointer = logical + buffer->startOffset;
        flushSize    = buffer->offset
                     - buffer->startOffset
                     + Command->reservedTail;

#if gcdDUMP_COMMAND
        _DumpCommand(Command, dataPointer, dataBytes);
        dataPointer = logical + buffer->startOffset;
        dataBytes   = buffer->offset - buffer->startOffset
                    + Command->reservedTail;
#endif

		/* Save pointer to next link. */
        link = logical + buffer->offset;
	}

	/* Compute number of bytes required for WAIT/LINK. */
	gcmkONERROR(
		gckHARDWARE_WaitLink(hardware,
							 gcvNULL,
							 Command->offset,
							 &bytes,
							 gcvNULL,
							 gcvNULL));

	lastRun = bytes;

	/* Grab the command queue mutex. */
	gcmkONERROR(
		gckOS_AcquireMutex(Command->os,
						   Command->mutexQueue,
						   gcvINFINITE));

	++acquired;

	if (Command->kernel->notifyIdle)
	{
		/* Increase the commit stamp */
		Command->commitStamp++;

		/* Set busy if idle */
		if (Command->idle)
		{
			Command->idle = gcvFALSE;

			gcmkVERIFY_OK(gckOS_NotifyIdle(Command->os, gcvFALSE));
		}
	}

	/* Compute number of bytes left in current command queue. */
	bytes = Command->pageSize - Command->offset;

	if (bytes < lastRun)
	{
        /* Create a new command queue. */
		gcmkONERROR(_NewQueue(Command, gcvTRUE));

		/* Adjust run size with any extra commands inserted. */
		lastRun += Command->offset;
	}

	/* Get current offset. */
	offset = Command->offset;

	/* Append WAIT/LINK in command queue. */
	bytes = Command->pageSize - offset;

	gcmkONERROR(
		gckHARDWARE_WaitLink(hardware,
							 (gctUINT8 *) Command->logical + offset,
							 offset,
							 &bytes,
							 &wait,
							 &waitSize));

    /* Flush the cache for the wait/link. */
    gcmkONERROR(gckOS_CacheFlush(Command->os,
                                 gcvNULL,
                                 (gctUINT8 *) Command->logical + offset,
                                 bytes));

#if gcdDUMP_COMMAND
    _DumpCommand(Command, (gctUINT8 *) Command->logical + offset, bytes);
#endif

	/* Adjust offset. */
	offset += bytes;

	if (Command->newQueue)
	{
		/* Compute fetch location and size for a new command queue. */
		fetchAddress = Command->logical;
		fetchSize    = offset;
	}
	else
	{
		/* Compute fetch location and size for an existing command queue. */
		fetchAddress = (gctUINT8 *) Command->logical + Command->offset;
		fetchSize    = offset - Command->offset;
	}

	bytes = 8;

	/* Link in WAIT/LINK. */
	gcmkONERROR(
		gckHARDWARE_Link(hardware,
						 link,
						 fetchAddress,
						 fetchSize,
						 &bytes));
#if MRVL_PRINT_CMD_BUFFER
	_AddLink(Command, link, fetchAddress);
#endif

    /* Flush the cache for the command buffer. */
    gcmkONERROR(gckOS_CacheFlush(Command->os,
                                 Process,
                                 flushPointer,
                                 flushSize));

#if gcdDUMP_COMMAND
    _DumpCommand(Command, dataPointer, dataBytes);
#endif

	/* Execute the entire sequence. */
	gcmkONERROR(
		gckHARDWARE_Link(hardware,
						 Command->wait,
						 initialLink,
						 initialSize,
						 &Command->waitSize));

    /* Flush the cache for the link. */
    gcmkONERROR(gckOS_CacheFlush(Command->os,
                                 gcvNULL,
                                 Command->wait,
                                 Command->waitSize));

#if gcdDUMP_COMMAND
    _DumpCommand(Command, Command->wait, Command->waitSize);
#endif

	/* Update command queue offset. */
	Command->offset   = offset;
	Command->newQueue = gcvFALSE;

	/* Update address of last WAIT. */
	Command->wait     = wait;
	Command->waitSize = waitSize;

	/* Update context and pipe select. */
	Command->currentContext = context->id;
	Command->pipeSelect     = context->currentPipe;

	/* Update queue tail pointer. */
	gcmkONERROR(
		gckHARDWARE_UpdateQueueTail(hardware,
									Command->logical,
									Command->offset));

#if gcdDUMP_COMMAND
    gcmkPRINT("@[kernel.commit]");
#endif

    /* Release the command queue mutex. */
    gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
    --acquired;

    /* Release the context switching mutex. */
    gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
    --acquired;

    /* Submit events if asked for. */
    if (Command->submit)
    {
        /* Submit events. */
        status = gckEVENT_Submit(Command->kernel->event, gcvFALSE, gcvFALSE);

        if (gcmIS_SUCCESS(status))
        {
            /* Success. */
            Command->submit = gcvFALSE;
        }
        else
        {
            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_COMMAND,
                           "gckEVENT_Submit returned %d",
                           status);
        }
    }

    /* Success. */
    status = gcvSTATUS_OK;

OnError:
	if (acquired > 1)
	{
		/* Release the command queue mutex. */
		gcmkVERIFY_OK(
			gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
	}

	if (acquired > 0)
	{
		/* Release the context switching mutex. */
		gcmkVERIFY_OK(
			gckOS_ReleaseMutex(Command->os, Command->mutexContext));
	}

	/* Unmap all mapped pointers. */
	while (stack != gcvNULL)
	{
		gcsMAPPED_PTR map = stack;
		stack             = map->next;

		gcmkVERIFY_OK(
			gckOS_UnmapUserPointer(Command->os,
								   map->pointer,
								   map->bytes,
								   map->kernelPointer));

		gcmkVERIFY_OK(
			gckOS_Free(Command->os, map));
	}

	/* Return status. */
	gcmkFOOTER();
	return status;
}
コード例 #23
0
/*******************************************************************************
**	InitializeVGProfiler
**
**	Initialize the profiler for the context provided.
**
**	Arguments:
**
**		VGContext Context
**			Pointer to a new VGContext object.
*/
void
InitializeVGProfiler(
    _VGContext * Context
	)
{
	gceSTATUS status;
	gctUINT rev;
        char *env;

	status = gcoPROFILER_Initialize(Context->hal);

	if (gcmIS_ERROR(status))
	{
		Context->profiler.enable = gcvFALSE;
		return;
	}

    /* Clear the profiler. */
	gcmVERIFY_OK(
		gcoOS_ZeroMemory(&Context->profiler, gcmSIZEOF(Context->profiler)));

    gcoOS_GetEnv(Context->os, "VP_COUNTER_FILTER", &env);
    if ((env == gcvNULL) || (env[0] ==0))
    {
        Context->profiler.drvEnable =
            Context->profiler.timeEnable =
            Context->profiler.memEnable = gcvTRUE;
    }
    else
    {
        gctSIZE_T bitsLen;
        gcoOS_StrLen(env, &bitsLen);
        if (bitsLen > 0)
        {
            Context->profiler.timeEnable = (env[0] == '1');
        }
        else
        {
            Context->profiler.timeEnable = gcvTRUE;
        }
        if (bitsLen > 1)
        {
            Context->profiler.memEnable = (env[1] == '1');
        }
        else
        {
            Context->profiler.memEnable = gcvTRUE;
        }
        if (bitsLen > 4)
        {
            Context->profiler.drvEnable = (env[4] == '1');
        }
        else
        {
            Context->profiler.drvEnable = gcvTRUE;
        }
    }

    Context->profiler.enable = gcvTRUE;

#if gcdNEW_PROFILER_FILE
    {
        /* Write Generic Info. */
        char* infoCompany = "Vivante Corporation";
        char* infoVersion = "1.0";
        char  infoRevision[255] = {'\0'};   /* read from hw */
        char* infoRenderer = Context->chipName;
        char* infoDriver = "OpenVG 1.1";
        gctUINT offset = 0;
        rev = Context->revision;
#define BCD(digit)      ((rev >> (digit * 4)) & 0xF)
        gcoOS_MemFill(infoRevision, 0, gcmSIZEOF(infoRevision));
        gcoOS_MemFill(infoRevision, 0, gcmSIZEOF(infoRevision));
        if (BCD(3) == 0)
        {
            /* Old format. */
            gcoOS_PrintStrSafe(infoRevision, gcmSIZEOF(infoRevision),
                &offset, "revision=\"%d.%d\" ", BCD(1), BCD(0));
        }
        else
        {
            /* New format. */
            gcoOS_PrintStrSafe(infoRevision, gcmSIZEOF(infoRevision),
                &offset, "revision=\"%d.%d.%d_rc%d\" ",
                BCD(3), BCD(2), BCD(1), BCD(0));
        }


        gcmWRITE_CONST(VPG_INFO);

        gcmWRITE_CONST(VPC_INFOCOMPANY);
        gcmWRITE_STRING(infoCompany);
        gcmWRITE_CONST(VPC_INFOVERSION);
        gcmWRITE_STRING(infoVersion);
        gcmWRITE_CONST(VPC_INFORENDERER);
        gcmWRITE_STRING(infoRenderer);
        gcmWRITE_CONST(VPC_INFOREVISION);
        gcmWRITE_STRING(infoRevision);
        gcmWRITE_CONST(VPC_INFODRIVER);
        gcmWRITE_STRING(infoDriver);

        gcmWRITE_CONST(VPG_END);
    }
#else
    /* Print generic info */
    _Print(Context, "<GenericInfo company=\"Vivante Corporation\" "
		"version=\"%d.%d\" renderer=\"%s\" ",
		1, 0, Context->chipName);

   	rev = Context->revision;
#define BCD(digit)		((rev >> (digit * 4)) & 0xF)
   	if (BCD(3) == 0)
   	{
   		/* Old format. */
   		_Print(Context, "revision=\"%d.%d\" ", BCD(1), BCD(0));
   	}
   	else
   	{
   		/* New format. */
   		_Print(Context, "revision=\"%d.%d.%d_rc%d\" ",
   			   BCD(3), BCD(2), BCD(1), BCD(0));
   	}
    _Print(Context, "driver=\"%s\" />\n", "OpenVG 1.1");
#endif

	gcoOS_GetTime(&Context->profiler.frameStart);
    Context->profiler.frameStartTimeusec     = Context->profiler.frameStart;
    Context->profiler.primitiveStartTimeusec = Context->profiler.frameStart;
	gcoOS_GetCPUTime(&Context->profiler.frameStartCPUTimeusec);
}
コード例 #24
0
/*******************************************************************************
**  gckKERNEL_NewDatabase
**
**  Create a new database structure and insert it to the head of the hash list.
**
**  INPUT:
**
**      gckKERNEL Kernel
**          Pointer to a gckKERNEL object.
**
**      gctUINT32 ProcessID
**          ProcessID that identifies the database.
**
**  OUTPUT:
**
**      gcsDATABASE_PTR * Database
**          Pointer to a variable receiving the database structure pointer on
**          success.
*/
static gceSTATUS
gckKERNEL_NewDatabase(
    IN gckKERNEL Kernel,
    IN gctUINT32 ProcessID,
    OUT gcsDATABASE_PTR * Database
    )
{
    gceSTATUS status;
    gcsDATABASE_PTR database;
    gctBOOL acquired = gcvFALSE;
    gctSIZE_T slot;
    gcsDATABASE_PTR existingDatabase;

    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);

    /* Acquire the database mutex. */
    gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
    acquired = gcvTRUE;

    /* Compute the hash for the database. */
    slot = ProcessID % gcmCOUNTOF(Kernel->db->db);

    /* Walk the hash list. */
    for (existingDatabase = Kernel->db->db[slot];
         existingDatabase != gcvNULL;
         existingDatabase = existingDatabase->next)
    {
        if (existingDatabase->processID == ProcessID)
        {
            /* One process can't be added twice. */
            gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
        }
    }

    if (Kernel->db->freeDatabase != gcvNULL)
    {
        /* Allocate a database from the free list. */
        database             = Kernel->db->freeDatabase;
        Kernel->db->freeDatabase = database->next;
    }
    else
    {
        gctPOINTER pointer = gcvNULL;

        /* Allocate a new database from the heap. */
        gcmkONERROR(gckOS_Allocate(Kernel->os,
                                   gcmSIZEOF(gcsDATABASE),
                                   &pointer));

        database = pointer;
    }

    /* Insert the database into the hash. */
    database->next   = Kernel->db->db[slot];
    Kernel->db->db[slot] = database;

    /* Save the hash slot. */
    database->slot = slot;

    /* Release the database mutex. */
    gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));

    /* Return the database. */
    *Database = database;

    /* Success. */
    gcmkFOOTER_ARG("*Database=0x%x", *Database);
    return gcvSTATUS_OK;

OnError:
    if (acquired)
    {
        /* Release the database mutex. */
        gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
    }

    /* Return the status. */
    gcmkFOOTER();
    return status;
}
コード例 #25
0
gceSTATUS
gcoPROFILER_Initialize(
	IN gcoHAL Hal
	)
{
    gceSTATUS status = gcvSTATUS_OK;
    char* fileName;
    char* filter = gcvNULL;
    gctSTRING portName;
    gctINT port;
	gcsHAL_INTERFACE iface;

    gcmHEADER();

    /* Check if already initialized. */
   	if (gcPLS.hal->profiler.enable)
    {
        gcPLS.hal->profiler.enable++;
        gcmFOOTER();
        return status;
    }

	/* Get profile setting. */
	iface.command = gcvHAL_GET_PROFILE_SETTING;

	/* Call the kernel. */
	status = gcoOS_DeviceControl(gcvNULL,
								 IOCTL_GCHAL_INTERFACE,
								 &iface, gcmSIZEOF(iface),
								 &iface, gcmSIZEOF(iface));

	if (gcmIS_ERROR(status) || !iface.u.GetProfileSetting.enable)
	{
    	gcPLS.hal->profiler.enable = 0;
        status = gcvSTATUS_GENERIC_IO;

        gcmFOOTER();
        return status;
	}

	gcmVERIFY_OK(gcoOS_ZeroMemory(&gcPLS.hal->profiler, gcmSIZEOF(gcPLS.hal->profiler)));

    gcoOS_GetEnv(gcvNULL,
                 "VP_COUNTER_FILTER",
                 &filter);

    /* Enable/Disable specific counters. */
    if ((filter != gcvNULL))
    {
        gctSIZE_T bitsLen;
        gcoOS_StrLen(filter, &bitsLen);
        if (bitsLen > 2)
        {
            gcPLS.hal->profiler.enableHal = (filter[2] == '1');
        }
        else
        {
            gcPLS.hal->profiler.enableHal = gcvTRUE;
        }

        if (bitsLen > 3)
        {
            gcPLS.hal->profiler.enableHW = (filter[3] == '1');
        }
        else
        {
            gcPLS.hal->profiler.enableHW = gcvTRUE;
        }

        if (bitsLen > 8)
        {
            gcPLS.hal->profiler.enableSH = (filter[8] == '1');
        }
        else
        {
            gcPLS.hal->profiler.enableSH = gcvTRUE;
        }
    }
    else
    {
        gcPLS.hal->profiler.enableHal = gcvTRUE;
        gcPLS.hal->profiler.enableHW = gcvTRUE;
        gcPLS.hal->profiler.enableSH = gcvTRUE;
    }

	gcoOS_GetEnv(gcvNULL,
				 "VPROFILER_OUTPUT",
				 &fileName);

    gcPLS.hal->profiler.useSocket = gcvFALSE;
	if (fileName && *fileName != '\0' && *fileName != ' ')
	{
        /* Extract port info. */
        gcoOS_StrFindReverse(fileName, ':', &portName);

        if (portName)
        {
            gcoOS_StrToInt(portName + 1, &port);

            if (port > 0)
            {
                /*status = gcoOS_Socket(gcvNULL, AF_INET, SOCK_STREAM, 0, &gcPLS.hal->profiler.sockFd);*/
                status = gcoOS_Socket(gcvNULL, 2, 1, 0, &gcPLS.hal->profiler.sockFd);

                if (gcmIS_SUCCESS(status))
                {
                    *portName = '\0';
                    status = gcoOS_Connect(gcvNULL,
                            gcPLS.hal->profiler.sockFd, fileName, port);
                    *portName = ':';

                    if (gcmIS_SUCCESS(status))
	                {
                        gcPLS.hal->profiler.useSocket = gcvTRUE;
                    }
                }
            }
        }
	}
    else
    {
		fileName = iface.u.GetProfileSetting.fileName;
    }

    if (! gcPLS.hal->profiler.useSocket)
	{
		status = gcoOS_Open(gcvNULL,
							fileName,
#ifdef gcdNEW_PROFILER_FILE
							gcvFILE_CREATE,
#else
							gcvFILE_CREATETEXT,
#endif
							&gcPLS.hal->profiler.file);
	}

    if (gcmIS_ERROR(status))
	{
    	gcPLS.hal->profiler.enable = 0;
        status = gcvSTATUS_GENERIC_IO;

        gcmFOOTER();
        return status;
	}

    gcPLS.hal->profiler.enable = 1;
	gcoOS_GetTime(&gcPLS.hal->profiler.frameStart);
	gcPLS.hal->profiler.frameStartTimeusec = gcPLS.hal->profiler.frameStart;
	gcPLS.hal->profiler.prevVSInstCount = 0;
	gcPLS.hal->profiler.prevVSBranchInstCount = 0;
	gcPLS.hal->profiler.prevVSTexInstCount = 0;
	gcPLS.hal->profiler.prevVSVertexCount = 0;
	gcPLS.hal->profiler.prevPSInstCount = 0;
	gcPLS.hal->profiler.prevPSBranchInstCount = 0;
	gcPLS.hal->profiler.prevPSTexInstCount = 0;
	gcPLS.hal->profiler.prevPSPixelCount = 0;

#if gcdNEW_PROFILER_FILE
    gcmWRITE_CONST(VPHEADER);
    gcmWRITE_BUFFER(4, "VP12");
#else
	gcmWRITE_STRING("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<VProfile>\n");
#endif

    /* Success. */
    gcmFOOTER();
    return status;
}
コード例 #26
0
ファイル: gc_vg_arc.c プロジェクト: Astralix/hardware_drivers
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;
}
コード例 #27
0
/*#endif*/

    gcmFOOTER_NO();
    return gcvSTATUS_OK;
}

#endif /* vivante_no_3d */
gceSTATUS
gcoPROFILER_EndFrame(
    IN gcoHAL Hal
    )
{
/*#if	(PROFILE_HAL_COUNTERS || PROFILE_HW_COUNTERS)*/
	gcsHAL_INTERFACE iface;
    gceSTATUS status;
/*#endif*/

    gcmHEADER();

	if (!gcPLS.hal->profiler.enable)
	{
        gcmFOOTER_NO();
		return gcvSTATUS_OK;
	}

/*#if PROFILE_HAL_COUNTERS*/
    if (gcPLS.hal->profiler.enableHal)
    {
#if gcdNEW_PROFILER_FILE
        gcmWRITE_CONST(VPG_HAL);

        gcmWRITE_COUNTER(VPC_HALVERTBUFNEWBYTEALLOC, gcPLS.hal->profiler.vertexBufferNewBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALVERTBUFTOTALBYTEALLOC, gcPLS.hal->profiler.vertexBufferTotalBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALVERTBUFNEWOBJALLOC, gcPLS.hal->profiler.vertexBufferNewObjectsAlloc);
        gcmWRITE_COUNTER(VPC_HALVERTBUFTOTALOBJALLOC, gcPLS.hal->profiler.vertexBufferTotalObjectsAlloc);

        gcmWRITE_COUNTER(VPC_HALINDBUFNEWBYTEALLOC, gcPLS.hal->profiler.indexBufferNewBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALINDBUFTOTALBYTEALLOC, gcPLS.hal->profiler.indexBufferTotalBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALINDBUFNEWOBJALLOC, gcPLS.hal->profiler.indexBufferNewObjectsAlloc);
        gcmWRITE_COUNTER(VPC_HALINDBUFTOTALOBJALLOC, gcPLS.hal->profiler.indexBufferTotalObjectsAlloc);

        gcmWRITE_COUNTER(VPC_HALTEXBUFNEWBYTEALLOC, gcPLS.hal->profiler.textureBufferNewBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALTEXBUFTOTALBYTEALLOC, gcPLS.hal->profiler.textureBufferTotalBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALTEXBUFNEWOBJALLOC, gcPLS.hal->profiler.textureBufferNewObjectsAlloc);
        gcmWRITE_COUNTER(VPC_HALTEXBUFTOTALOBJALLOC, gcPLS.hal->profiler.textureBufferTotalObjectsAlloc);

        gcmWRITE_CONST(VPG_END);
#else
    	gcmWRITE_STRING("<HALCounters>\n");

	    gcmPRINT_XML_COUNTER(vertexBufferNewBytesAlloc);
    	gcmPRINT_XML_COUNTER(vertexBufferTotalBytesAlloc);
	    gcmPRINT_XML_COUNTER(vertexBufferNewObjectsAlloc);
    	gcmPRINT_XML_COUNTER(vertexBufferTotalObjectsAlloc);

	    gcmPRINT_XML_COUNTER(indexBufferNewBytesAlloc);
    	gcmPRINT_XML_COUNTER(indexBufferTotalBytesAlloc);
	    gcmPRINT_XML_COUNTER(indexBufferNewObjectsAlloc);
    	gcmPRINT_XML_COUNTER(indexBufferTotalObjectsAlloc);

	    gcmPRINT_XML_COUNTER(textureBufferNewBytesAlloc);
    	gcmPRINT_XML_COUNTER(textureBufferTotalBytesAlloc);
	    gcmPRINT_XML_COUNTER(textureBufferNewObjectsAlloc);
    	gcmPRINT_XML_COUNTER(textureBufferTotalObjectsAlloc);

	    gcmWRITE_STRING("</HALCounters>\n");
#endif

	    /* Reset per-frame counters. */
    	gcPLS.hal->profiler.vertexBufferNewBytesAlloc   = 0;
	    gcPLS.hal->profiler.vertexBufferNewObjectsAlloc = 0;

	    gcPLS.hal->profiler.indexBufferNewBytesAlloc   = 0;
    	gcPLS.hal->profiler.indexBufferNewObjectsAlloc = 0;

	    gcPLS.hal->profiler.textureBufferNewBytesAlloc   = 0;
  		gcPLS.hal->profiler.textureBufferNewObjectsAlloc = 0;
	}
/*#endif*/

/*#if PROFILE_HW_COUNTERS*/
    /* gcvHAL_READ_ALL_PROFILE_REGISTERS. */
    if (gcPLS.hal->profiler.enableHW)
    {
		iface.command = gcvHAL_READ_ALL_PROFILE_REGISTERS;

		/* Call the kernel. */
		status = gcoOS_DeviceControl(gcvNULL,
									 IOCTL_GCHAL_INTERFACE,
									 &iface, gcmSIZEOF(iface),
									 &iface, gcmSIZEOF(iface));

		/* Verify result. */
		if (gcmNO_ERROR(status))
		{
        #define gcmCOUNTER(name)    iface.u.RegisterProfileData.counters.name

#if gcdNEW_PROFILER_FILE
            gcmWRITE_CONST(VPG_HW);
            gcmWRITE_CONST(VPG_GPU);
            gcmWRITE_COUNTER(VPC_GPUREAD64BYTE, gcmCOUNTER(gpuTotalRead64BytesPerFrame));
            gcmWRITE_COUNTER(VPC_GPUWRITE64BYTE, gcmCOUNTER(gpuTotalWrite64BytesPerFrame));
            gcmWRITE_COUNTER(VPC_GPUCYCLES, gcmCOUNTER(gpuCyclesCounter));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_VS);
            gcmWRITE_COUNTER(VPC_VSINSTCOUNT, gcmCOUNTER(vs_inst_counter) - gcPLS.hal->profiler.prevVSInstCount);
            gcmWRITE_COUNTER(VPC_VSBRANCHINSTCOUNT, gcmCOUNTER(vtx_branch_inst_counter) - gcPLS.hal->profiler.prevVSBranchInstCount);
            gcmWRITE_COUNTER(VPC_VSTEXLDINSTCOUNT, gcmCOUNTER(vtx_texld_inst_counter) - gcPLS.hal->profiler.prevVSTexInstCount);
			gcmWRITE_COUNTER(VPC_VSRENDEREDVERTCOUNT, gcmCOUNTER(rendered_vertice_counter) - gcPLS.hal->profiler.prevVSVertexCount);
            gcmWRITE_CONST(VPG_END);

			gcPLS.hal->profiler.prevVSInstCount = gcmCOUNTER(vs_inst_counter);
			gcPLS.hal->profiler.prevVSBranchInstCount = gcmCOUNTER(vtx_branch_inst_counter);
			gcPLS.hal->profiler.prevVSTexInstCount = gcmCOUNTER(vtx_texld_inst_counter);
			gcPLS.hal->profiler.prevVSVertexCount = gcmCOUNTER(rendered_vertice_counter);

            gcmWRITE_CONST(VPG_PA);
            gcmWRITE_COUNTER(VPC_PAINVERTCOUNT, gcmCOUNTER(pa_input_vtx_counter));
            gcmWRITE_COUNTER(VPC_PAINPRIMCOUNT, gcmCOUNTER(pa_input_prim_counter));
            gcmWRITE_COUNTER(VPC_PAOUTPRIMCOUNT, gcmCOUNTER(pa_output_prim_counter));
            gcmWRITE_COUNTER(VPC_PADEPTHCLIPCOUNT, gcmCOUNTER(pa_depth_clipped_counter));
            gcmWRITE_COUNTER(VPC_PATRIVIALREJCOUNT, gcmCOUNTER(pa_trivial_rejected_counter));
            gcmWRITE_COUNTER(VPC_PACULLCOUNT, gcmCOUNTER(pa_culled_counter));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_SETUP);
            gcmWRITE_COUNTER(VPC_SETRIANGLECOUNT, gcmCOUNTER(se_culled_triangle_count));
            gcmWRITE_COUNTER(VPC_SELINECOUNT, gcmCOUNTER(se_culled_lines_count));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_RA);
            gcmWRITE_COUNTER(VPC_RAVALIDPIXCOUNT, gcmCOUNTER(ra_valid_pixel_count));
            gcmWRITE_COUNTER(VPC_RATOTALQUADCOUNT, gcmCOUNTER(ra_total_quad_count));
            gcmWRITE_COUNTER(VPC_RAVALIDQUADCOUNTEZ, gcmCOUNTER(ra_valid_quad_count_after_early_z));
            gcmWRITE_COUNTER(VPC_RATOTALPRIMCOUNT, gcmCOUNTER(ra_total_primitive_count));
            gcmWRITE_COUNTER(VPC_RAPIPECACHEMISSCOUNT, gcmCOUNTER(ra_pipe_cache_miss_counter));
            gcmWRITE_COUNTER(VPC_RAPREFCACHEMISSCOUNT, gcmCOUNTER(ra_prefetch_cache_miss_counter));
            gcmWRITE_COUNTER(VPC_RAEEZCULLCOUNT, gcmCOUNTER(ra_eez_culled_counter));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_TX);
            gcmWRITE_COUNTER(VPC_TXTOTBILINEARREQ, gcmCOUNTER(tx_total_bilinear_requests));
            gcmWRITE_COUNTER(VPC_TXTOTTRILINEARREQ, gcmCOUNTER(tx_total_trilinear_requests));
            gcmWRITE_COUNTER(VPC_TXTOTTEXREQ, gcmCOUNTER(tx_total_texture_requests));
            gcmWRITE_COUNTER(VPC_TXMEMREADCOUNT, gcmCOUNTER(tx_mem_read_count));
            gcmWRITE_COUNTER(VPC_TXMEMREADIN8BCOUNT, gcmCOUNTER(tx_mem_read_in_8B_count));
            gcmWRITE_COUNTER(VPC_TXCACHEMISSCOUNT, gcmCOUNTER(tx_cache_miss_count));
            gcmWRITE_COUNTER(VPC_TXCACHEHITTEXELCOUNT, gcmCOUNTER(tx_cache_hit_texel_count));
            gcmWRITE_COUNTER(VPC_TXCACHEMISSTEXELCOUNT, gcmCOUNTER(tx_cache_miss_texel_count));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_PS);
            gcmWRITE_COUNTER(VPC_PSINSTCOUNT, gcmCOUNTER(ps_inst_counter) - gcPLS.hal->profiler.prevPSInstCount);
            gcmWRITE_COUNTER(VPC_PSBRANCHINSTCOUNT, gcmCOUNTER(pxl_branch_inst_counter) - gcPLS.hal->profiler.prevPSBranchInstCount);
            gcmWRITE_COUNTER(VPC_PSTEXLDINSTCOUNT, gcmCOUNTER(pxl_texld_inst_counter) - gcPLS.hal->profiler.prevPSTexInstCount);
			gcmWRITE_COUNTER(VPC_PSRENDEREDPIXCOUNT, gcmCOUNTER(rendered_pixel_counter) - gcPLS.hal->profiler.prevPSPixelCount);
            gcmWRITE_CONST(VPG_END);

			gcPLS.hal->profiler.prevPSInstCount = gcmCOUNTER(ps_inst_counter);
			gcPLS.hal->profiler.prevPSBranchInstCount = gcmCOUNTER(pxl_branch_inst_counter);
			gcPLS.hal->profiler.prevPSTexInstCount = gcmCOUNTER(pxl_texld_inst_counter);
			gcPLS.hal->profiler.prevPSPixelCount = gcmCOUNTER(rendered_pixel_counter);

            gcmWRITE_CONST(VPG_PE);
            gcmWRITE_COUNTER(VPC_PEKILLEDBYCOLOR, gcmCOUNTER(pe_pixel_count_killed_by_color_pipe));
            gcmWRITE_COUNTER(VPC_PEKILLEDBYDEPTH, gcmCOUNTER(pe_pixel_count_killed_by_depth_pipe));
            gcmWRITE_COUNTER(VPC_PEDRAWNBYCOLOR, gcmCOUNTER(pe_pixel_count_drawn_by_color_pipe));
            gcmWRITE_COUNTER(VPC_PEDRAWNBYDEPTH, gcmCOUNTER(pe_pixel_count_drawn_by_depth_pipe));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_MC);
            gcmWRITE_COUNTER(VPC_MCREADREQ8BPIPE, gcmCOUNTER(mc_total_read_req_8B_from_pipeline));
            gcmWRITE_COUNTER(VPC_MCREADREQ8BIP, gcmCOUNTER(mc_total_read_req_8B_from_IP));
            gcmWRITE_COUNTER(VPC_MCWRITEREQ8BPIPE, gcmCOUNTER(mc_total_write_req_8B_from_pipeline));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_AXI);
            gcmWRITE_COUNTER(VPC_AXIREADREQSTALLED, gcmCOUNTER(hi_axi_cycles_read_request_stalled));
            gcmWRITE_COUNTER(VPC_AXIWRITEREQSTALLED, gcmCOUNTER(hi_axi_cycles_write_request_stalled));
            gcmWRITE_COUNTER(VPC_AXIWRITEDATASTALLED, gcmCOUNTER(hi_axi_cycles_write_data_stalled));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_END);
#else
		    gcmWRITE_STRING("<HWCounters>\n");

	        gcmPRINT_XML("<read_64Byte value=\"%u\"/>\n",
    	    			 gcmCOUNTER(gpuTotalRead64BytesPerFrame));
        	gcmPRINT_XML("<write_64Byte value=\"%u\"/>\n",
	        			 gcmCOUNTER(gpuTotalWrite64BytesPerFrame));
	        gcmPRINT_XML("<gpu_cycles value=\"%u\"/>\n",
    	    			 gcmCOUNTER(gpuCyclesCounter));
        	gcmPRINT_XML("<pe_pixel_count_killed_by_color_pipe value=\"%u\"/>\n",
        				 gcmCOUNTER(pe_pixel_count_killed_by_color_pipe));
	        gcmPRINT_XML("<pe_pixel_count_killed_by_depth_pipe value=\"%u\"/>\n",
    	    			 gcmCOUNTER(pe_pixel_count_killed_by_depth_pipe));
        	gcmPRINT_XML("<pe_pixel_count_drawn_by_color_pipe value=\"%u\"/>\n",
						 gcmCOUNTER(pe_pixel_count_drawn_by_color_pipe));
	        gcmPRINT_XML("<pe_pixel_count_drawn_by_depth_pipe value=\"%u\"/>\n",
						 gcmCOUNTER(pe_pixel_count_drawn_by_depth_pipe));
        	gcmPRINT_XML("<ps_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(ps_inst_counter));
	        gcmPRINT_XML("<rendered_pixel_counter value=\"%u\"/>\n",
						 gcmCOUNTER(rendered_pixel_counter));
        	gcmPRINT_XML("<vs_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(vs_inst_counter));
	        gcmPRINT_XML("<rendered_vertice_counter value=\"%u\"/>\n",
						 gcmCOUNTER(rendered_vertice_counter));
        	gcmPRINT_XML("<vtx_branch_inst_counter value=\"%u\"/>\n",
					 gcmCOUNTER(vtx_branch_inst_counter));
	        gcmPRINT_XML("<vtx_texld_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(vtx_texld_inst_counter));
        	gcmPRINT_XML("<pxl_branch_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pxl_branch_inst_counter));
	        gcmPRINT_XML("<pxl_texld_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pxl_texld_inst_counter));
        	gcmPRINT_XML("<pa_input_vtx_counter value=\"%u\"/>\n",
					 gcmCOUNTER(pa_input_vtx_counter));
	        gcmPRINT_XML("<pa_input_prim_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pa_input_prim_counter));
        	gcmPRINT_XML("<pa_output_prim_counter value=\"%u\"/>\n",
					 gcmCOUNTER(pa_output_prim_counter));
	        gcmPRINT_XML("<pa_depth_clipped_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pa_depth_clipped_counter));
        	gcmPRINT_XML("<pa_trivial_rejected_counter value=\"%u\"/>\n",
					 gcmCOUNTER(pa_trivial_rejected_counter));
	        gcmPRINT_XML("<pa_culled_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pa_culled_counter));
        	gcmPRINT_XML("<se_culled_triangle_count value=\"%u\"/>\n",
						 gcmCOUNTER(se_culled_triangle_count));
	        gcmPRINT_XML("<se_culled_lines_count value=\"%u\"/>\n",
						 gcmCOUNTER(se_culled_lines_count));
        	gcmPRINT_XML("<ra_valid_pixel_count value=\"%u\"/>\n",
					 gcmCOUNTER(ra_valid_pixel_count));
	        gcmPRINT_XML("<ra_total_quad_count value=\"%u\"/>\n",
						 gcmCOUNTER(ra_total_quad_count));
        	gcmPRINT_XML("<ra_valid_quad_count_after_early_z value=\"%u\"/>\n",
					 gcmCOUNTER(ra_valid_quad_count_after_early_z));
	        gcmPRINT_XML("<ra_total_primitive_count value=\"%u\"/>\n",
						 gcmCOUNTER(ra_total_primitive_count));
        	gcmPRINT_XML("<ra_pipe_cache_miss_counter value=\"%u\"/>\n",
						 gcmCOUNTER(ra_pipe_cache_miss_counter));
	        gcmPRINT_XML("<ra_prefetch_cache_miss_counter value=\"%u\"/>\n",
						 gcmCOUNTER(ra_prefetch_cache_miss_counter));
        	gcmPRINT_XML("<ra_eez_culled_counter value=\"%u\"/>\n",
					 gcmCOUNTER(ra_eez_culled_counter));
	        gcmPRINT_XML("<tx_total_bilinear_requests value=\"%u\"/>\n",
						 gcmCOUNTER(tx_total_bilinear_requests));
        	gcmPRINT_XML("<tx_total_trilinear_requests value=\"%u\"/>\n",
					 gcmCOUNTER(tx_total_trilinear_requests));
	        gcmPRINT_XML("<tx_total_discarded_texture_requests value=\"%u\"/>\n",
						 gcmCOUNTER(tx_total_discarded_texture_requests));
        	gcmPRINT_XML("<tx_total_texture_requests value=\"%u\"/>\n",
						 gcmCOUNTER(tx_total_texture_requests));
    	    gcmPRINT_XML("<tx_mem_read_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_mem_read_count));
	        gcmPRINT_XML("<tx_mem_read_in_8B_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_mem_read_in_8B_count));
        	gcmPRINT_XML("<tx_cache_miss_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_cache_miss_count));
    	    gcmPRINT_XML("<tx_cache_hit_texel_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_cache_hit_texel_count));
	        gcmPRINT_XML("<tx_cache_miss_texel_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_cache_miss_texel_count));
        	gcmPRINT_XML("<mc_total_read_req_8B_from_pipeline value=\"%u\"/>\n",
						 gcmCOUNTER(mc_total_read_req_8B_from_pipeline));
    	    gcmPRINT_XML("<mc_total_read_req_8B_from_IP value=\"%u\"/>\n",
						 gcmCOUNTER(mc_total_read_req_8B_from_IP));
	        gcmPRINT_XML("<mc_total_write_req_8B_from_pipeline value=\"%u\"/>\n",
						 gcmCOUNTER(mc_total_write_req_8B_from_pipeline));
	        gcmPRINT_XML("<hi_axi_cycles_read_request_stalled value=\"%u\"/>\n",
						 gcmCOUNTER(hi_axi_cycles_read_request_stalled));
	        gcmPRINT_XML("<hi_axi_cycles_write_request_stalled value=\"%u\"/>\n",
						 gcmCOUNTER(hi_axi_cycles_write_request_stalled));
        	gcmPRINT_XML("<hi_axi_cycles_write_data_stalled value=\"%u\"/>\n",
						 gcmCOUNTER(hi_axi_cycles_write_data_stalled));

	    	gcmWRITE_STRING("</HWCounters>\n");
#endif
		}
	}
/*#endif*/

	/* Success. */
    gcmFOOTER_NO();
    return gcvSTATUS_OK;
}
コード例 #28
0
gceSTATUS
gckKERNEL_Construct(
	IN gckOS Os,
	IN gctPOINTER Context,
	OUT gckKERNEL * Kernel
	)
{
	gckKERNEL kernel = gcvNULL;
	gceSTATUS status;

	gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);

	/* Verify the arguments. */
	gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
	gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);

	/* Allocate the gckKERNEL object. */
	gcmkONERROR(
		gckOS_Allocate(Os,
					   gcmSIZEOF(struct _gckKERNEL),
					   (gctPOINTER *) &kernel));
#if MRVL_LOW_POWER_MODE_DEBUG
    gcmERR_RETURN(
		gckOS_Allocate(Os, 0x1000000, (gctPOINTER *) &kernel->kernelMSG));

    kernel->msgLen = 0;
#endif

	/* Zero the object pointers. */
	kernel->hardware = gcvNULL;
	kernel->command  = gcvNULL;
	kernel->event    = gcvNULL;
	kernel->mmu      = gcvNULL;

	/* Initialize the gckKERNEL object. */
	kernel->object.type = gcvOBJ_KERNEL;
	kernel->os          = Os;

	/* Save context. */
	kernel->context = Context;

    /* Construct atom holding number of clients. */
    kernel->atomClients = gcvNULL;
    gcmkONERROR(gckOS_AtomConstruct(Os, &kernel->atomClients));
#if gcdSECURE_USER
    kernel->cacheSlots     = 0;
    kernel->cacheTimeStamp = 0;
#endif

	/* Construct the gckHARDWARE object. */
	gcmkONERROR(
		gckHARDWARE_Construct(Os, &kernel->hardware));

	/* Set pointer to gckKERNEL object in gckHARDWARE object. */
	kernel->hardware->kernel = kernel;

	/* Initialize the hardware. */
	gcmkONERROR(
		gckHARDWARE_InitializeHardware(kernel->hardware));

	/* Construct the gckCOMMAND object. */
	gcmkONERROR(
		gckCOMMAND_Construct(kernel, &kernel->command));

	/* Construct the gckEVENT object. */
	gcmkONERROR(
		gckEVENT_Construct(kernel, &kernel->event));

	/* Construct the gckMMU object. */
	gcmkONERROR(
		gckMMU_Construct(kernel, gcdMMU_SIZE, &kernel->mmu));
	kernel->notifyIdle = gcvTRUE; /* gcvFALSE; */

#if VIVANTE_PROFILER
	/* Initialize profile setting */
#if defined ANDROID
	kernel->profileEnable = gcvFALSE;
#else
	kernel->profileEnable = gcvTRUE;
#endif

	gcmkVERIFY_OK(
		gckOS_MemCopy(kernel->profileFileName,
					  DEFAULT_PROFILE_FILE_NAME,
					  gcmSIZEOF(DEFAULT_PROFILE_FILE_NAME) + 1));
#endif

	/* Return pointer to the gckKERNEL object. */
	*Kernel = kernel;

	/* Success. */
	gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
	return gcvSTATUS_OK;

OnError:
	if (kernel != gcvNULL)
	{
    	if (kernel->event != gcvNULL)
	    {
    	    gcmkVERIFY_OK(gckEVENT_Destroy(kernel->event));
    	}

   	 	if (kernel->command != gcvNULL)
    	{
		gcmkVERIFY_OK(gckCOMMAND_Destroy(kernel->command));
    	}

    	if (kernel->hardware != gcvNULL)
    	{
        	gcmkVERIFY_OK(gckHARDWARE_Destroy(kernel->hardware));
    	}

        if (kernel->atomClients != gcvNULL)
        {
            gcmkVERIFY_OK(gckOS_AtomDestroy(Os, kernel->atomClients));
        }

    kernel->version = _GC_VERSION_STRING_;

#if MRVL_LOW_POWER_MODE_DEBUG
	gcmkVERIFY_OK(
		gckOS_Free(Os, kernel->kernelMSG));
#endif
    	gcmkVERIFY_OK(gckOS_Free(Os, kernel));
	}

	/* Return the error. */
	gcmkFOOTER();
	return status;
}
コード例 #29
0
/*******************************************************************************
**
**  gckHEAP_Allocate
**
**  Allocate data from the heap.
**
**  INPUT:
**
**      gckHEAP Heap
**          Pointer to a gckHEAP object.
**
**      IN gctSIZE_T Bytes
**          Number of byte to allocate.
**
**  OUTPUT:
**
**      gctPOINTER * Memory
**          Pointer to a variable that will hold the address of the allocated
**          memory.
*/
gceSTATUS
gckHEAP_Allocate(
    IN gckHEAP Heap,
    IN gctSIZE_T Bytes,
    OUT gctPOINTER * Memory
    )
{
    gctBOOL acquired = gcvFALSE;
    gcskHEAP_PTR heap;
    gceSTATUS status;
    gctSIZE_T bytes;
    gcskNODE_PTR node, used, prevFree = gcvNULL;
    gctPOINTER memory = gcvNULL;

    gcmkHEADER_ARG("Heap=0x%x Bytes=%lu", Heap, Bytes);

    /* Verify the arguments. */
    gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
    gcmkVERIFY_ARGUMENT(Bytes > 0);
    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);

    /* Determine number of bytes required for a node. */
    bytes = gcmALIGN(Bytes + gcmSIZEOF(gcskNODE), 8);

    /* Acquire the mutex. */
    gcmkONERROR(
        gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));

    acquired = gcvTRUE;

    /* Check if this allocation is bigger than the default allocation size. */
    if (bytes > Heap->allocationSize - gcmSIZEOF(gcskHEAP) - gcmSIZEOF(gcskNODE))
    {
        /* Adjust allocation size. */
        Heap->allocationSize = bytes * 2;
    }

    else if (Heap->heap != gcvNULL)
    {
        gctINT i;

        /* 2 retries, since we might need to compact. */
        for (i = 0; i < 2; ++i)
        {
            /* Walk all the heaps. */
            for (heap = Heap->heap; heap != gcvNULL; heap = heap->next)
            {
                /* Check if this heap has enough bytes to hold the request. */
                if (bytes <= heap->size - gcmSIZEOF(gcskNODE))
                {
                    prevFree = gcvNULL;

                    /* Walk the chain of free nodes. */
                    for (node = heap->freeList;
                         node != gcvNULL;
                         node = node->next
                    )
                    {
                        gcmkASSERT(node->next != gcdIN_USE);

                        /* Check if this free node has enough bytes. */
                        if (node->bytes >= bytes)
                        {
                            /* Use the node. */
                            goto UseNode;
                        }

                        /* Save current free node for linked list management. */
                        prevFree = node;
                    }
                }
            }

            if (i == 0)
            {
                /* Compact the heap. */
                gcmkVERIFY_OK(_CompactKernelHeap(Heap));

#if gcmIS_DEBUG(gcdDEBUG_CODE)
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "===== KERNEL HEAP =====");
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Number of allocations           : %12u",
                               Heap->allocCount);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Number of bytes allocated       : %12llu",
                               Heap->allocBytes);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Maximum allocation size         : %12llu",
                               Heap->allocBytesMax);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Total number of bytes allocated : %12llu",
                               Heap->allocBytesTotal);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Number of heaps                 : %12u",
                               Heap->heapCount);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Heap memory in bytes            : %12llu",
                               Heap->heapMemory);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Maximum number of heaps         : %12u",
                               Heap->heapCountMax);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Maximum heap memory in bytes    : %12llu",
                               Heap->heapMemoryMax);
#endif
            }
        }
    }

    /* Release the mutex. */
    gcmkONERROR(
        gckOS_ReleaseMutex(Heap->os, Heap->mutex));

    acquired = gcvFALSE;

    /* Allocate a new heap. */
    gcmkONERROR(
        gckOS_AllocateMemory(Heap->os,
                             Heap->allocationSize,
                             &memory));

    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
                   "Allocated heap 0x%x (%lu bytes)",
                   memory, Heap->allocationSize);

    /* Acquire the mutex. */
    gcmkONERROR(
        gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));

    acquired = gcvTRUE;

    /* Use the allocated memory as the heap. */
    heap = (gcskHEAP_PTR) memory;

    /* Insert this heap to the head of the chain. */
    heap->next = Heap->heap;
    heap->prev = gcvNULL;
    heap->size = Heap->allocationSize - gcmSIZEOF(gcskHEAP);

    if (heap->next != gcvNULL)
    {
        heap->next->prev = heap;
    }
    Heap->heap = heap;

    /* Mark the end of the heap. */
    node = (gcskNODE_PTR) ( (gctUINT8_PTR) heap
                          + Heap->allocationSize
                          - gcmSIZEOF(gcskNODE)
                          );
    node->bytes = 0;
    node->next  = gcvNULL;

    /* Create a free list. */
    node           = (gcskNODE_PTR) (heap + 1);
    heap->freeList = node;

    /* Initialize the free list. */
    node->bytes = heap->size - gcmSIZEOF(gcskNODE);
    node->next  = gcvNULL;

    /* No previous free. */
    prevFree = gcvNULL;

#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
    /* Update profiling. */
    Heap->heapCount  += 1;
    Heap->heapMemory += Heap->allocationSize;

    if (Heap->heapCount > Heap->heapCountMax)
    {
        Heap->heapCountMax = Heap->heapCount;
    }
    if (Heap->heapMemory > Heap->heapMemoryMax)
    {
        Heap->heapMemoryMax = Heap->heapMemory;
    }
#endif

UseNode:
    /* Verify some stuff. */
    gcmkASSERT(heap != gcvNULL);
    gcmkASSERT(node != gcvNULL);
    gcmkASSERT(node->bytes >= bytes);

    if (heap->prev != gcvNULL)
    {
        /* Unlink the heap from the linked list. */
        heap->prev->next = heap->next;
        if (heap->next != gcvNULL)
        {
            heap->next->prev = heap->prev;
        }

        /* Move the heap to the front of the list. */
        heap->next       = Heap->heap;
        heap->prev       = gcvNULL;
        Heap->heap       = heap;
        heap->next->prev = heap;
    }

    /* Check if there is enough free space left after usage for another free
    ** node. */
    if (node->bytes - bytes >= gcmSIZEOF(gcskNODE))
    {
        /* Allocated used space from the back of the free list. */
        used = (gcskNODE_PTR) ((gctUINT8_PTR) node + node->bytes - bytes);

        /* Adjust the number of free bytes. */
        node->bytes -= bytes;
        gcmkASSERT(node->bytes >= gcmSIZEOF(gcskNODE));
    }
    else
    {
        /* Remove this free list from the chain. */
        if (prevFree == gcvNULL)
        {
            heap->freeList = node->next;
        }
        else
        {
            prevFree->next = node->next;
        }

        /* Consume the entire free node. */
        used  = (gcskNODE_PTR) node;
        bytes = node->bytes;
    }

    /* Mark node as used. */
    used->bytes     = bytes;
    used->next      = gcdIN_USE;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
    used->timeStamp = ++Heap->timeStamp;
#endif

#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
    /* Update profile counters. */
    Heap->allocCount      += 1;
    Heap->allocBytes      += bytes;
    Heap->allocBytesMax    = gcmMAX(Heap->allocBytes, Heap->allocBytesMax);
    Heap->allocBytesTotal += bytes;
#endif

    /* Release the mutex. */
    gcmkVERIFY_OK(
        gckOS_ReleaseMutex(Heap->os, Heap->mutex));

    /* Return pointer to memory. */
    *Memory = used + 1;

    /* Success. */
    gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
    return gcvSTATUS_OK;

OnError:
    if (acquired)
    {
        /* Release the mutex. */
        gcmkVERIFY_OK(
            gckOS_ReleaseMutex(Heap->os, Heap->mutex));
    }

    if (memory != gcvNULL)
    {
        /* Free the heap memory. */
        gckOS_FreeMemory(Heap->os, memory);
    }

    /* Return the status. */
    gcmkFOOTER();
    return status;
}
コード例 #30
0
/*******************************************************************************
**  gckKERNEL_QueryProcessDB
**
**  Query a process database for the current usage of a particular record type.
**
**  INPUT:
**
**      gckKERNEL Kernel
**          Pointer to a gckKERNEL object.
**
**      gctUINT32 ProcessID
**          Process ID used to identify the database.
**
**      gctBOOL LastProcessID
**          gcvTRUE if searching for the last known process ID.  gcvFALSE if
**          we need to search for the process ID specified by the ProcessID
**          argument.
**
**      gceDATABASE_TYPE Type
**          Type of the record to query.
**
**  OUTPUT:
**
**      gcuDATABASE_INFO * Info
**          Pointer to a variable that receives the requested information.
*/
gceSTATUS
gckKERNEL_QueryProcessDB(
    IN gckKERNEL Kernel,
    IN gctUINT32 ProcessID,
    IN gctBOOL LastProcessID,
    IN gceDATABASE_TYPE Type,
    OUT gcuDATABASE_INFO * Info
    )
{
    gceSTATUS status;
    gcsDATABASE_PTR database;

    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Info=0x%x",
                   Kernel, ProcessID, Type, Info);

    /* Verify the arguments. */
    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
    gcmkVERIFY_ARGUMENT(Info != gcvNULL);

    /* Find the database. */
    gcmkONERROR(
        gckKERNEL_FindDatabase(Kernel, ProcessID, LastProcessID, &database));

    /* Get pointer to counters. */
    switch (Type)
    {
    case gcvDB_VIDEO_MEMORY:
        gckOS_MemCopy(&Info->counters,
                                  &database->vidMem,
                                  gcmSIZEOF(database->vidMem));
        break;

    case gcvDB_NON_PAGED:
        gckOS_MemCopy(&Info->counters,
                                  &database->nonPaged,
                                  gcmSIZEOF(database->vidMem));
        break;

    case gcvDB_CONTIGUOUS:
        gckOS_MemCopy(&Info->counters,
                                  &database->contiguous,
                                  gcmSIZEOF(database->vidMem));
        break;

    case gcvDB_IDLE:
        Info->time           = Kernel->db->idleTime;
        Kernel->db->idleTime = 0;
        break;

    case gcvDB_MAP_MEMORY:
        gckOS_MemCopy(&Info->counters,
                                  &database->mapMemory,
                                  gcmSIZEOF(database->mapMemory));
        break;

    case gcvDB_MAP_USER_MEMORY:
        gckOS_MemCopy(&Info->counters,
                                  &database->mapUserMemory,
                                  gcmSIZEOF(database->mapUserMemory));
        break;

    default:
        break;
    }

    /* Success. */
    gcmkFOOTER_NO();
    return gcvSTATUS_OK;

OnError:
    /* Return the status. */
    gcmkFOOTER();
    return status;
}