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; }
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; }
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; }
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; }
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 }
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; }
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; }
void _glshInitializeRenderbuffer( GLContext Context ) { /* No renderbuffers bound yet. */ Context->renderbuffer = gcvNULL; /* No frame buffer objects. */ gcmVERIFY_OK(gcoOS_ZeroMemory(&Context->renderbufferObjects, gcmSIZEOF(Context->renderbufferObjects))); }
/******************************************************************************* ** ** _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; }
/** * * @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; }
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; }
/******************************************************************************* ** ** 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)); }
/******************************************************************************* ** ** 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; }
/******************************************************************************* ** ** 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; }
/******************************************************************************* ** ** 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; }
/******************************************************************************* ** 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; }
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; }
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; }
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; }
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; }
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; }
/******************************************************************************* ** ** 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; }
/******************************************************************************* ** 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); }
/******************************************************************************* ** 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; }
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; }
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; }
/*#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; }
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; }
/******************************************************************************* ** ** 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; }
/******************************************************************************* ** 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; }