/******************************************************************************* ** ** gcoBUFFER_Write ** ** Copy a number of bytes into the buffer. ** ** INPUT: ** ** gcoBUFFER Buffer ** Pointer to an gcoBUFFER object. ** ** gctCONST_POINTER Data ** Pointer to a buffer that contains the data to be copied. ** ** IN gctSIZE_T Bytes ** Number of bytes to copy. ** ** IN gctBOOL Aligned ** gcvTRUE if the data needs to be aligned to 64-bit. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoBUFFER_Write( IN gcoBUFFER Buffer, IN gctCONST_POINTER Data, IN gctSIZE_T Bytes, IN gctBOOL Aligned ) { gceSTATUS status; gcoCMDBUF reserve; gcmHEADER_ARG("Buffer=0x%x Data=0x%x Bytes=%lu Aligned=%d", Buffer, Data, Bytes, Aligned); /* Verify the arguments. */ gcmVERIFY_OBJECT(Buffer, gcvOBJ_BUFFER); gcmDEBUG_VERIFY_ARGUMENT(Data != gcvNULL); gcmDEBUG_VERIFY_ARGUMENT(Bytes > 0); /* Reserve data in the buffer. */ gcmONERROR(gcoBUFFER_Reserve(Buffer, Bytes, Aligned, &reserve)); /* Write data into the buffer. */ gcmONERROR(gcoOS_MemCopy(reserve->lastReserve, Data, Bytes)); /* Success. */ gcmFOOTER_NO(); return gcvSTATUS_OK; OnError: /* Return status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoBUFFER_Reserve ** ** Reserve a number of bytes in the buffer. ** ** INPUT: ** ** gcoBUFFER Buffer ** Pointer to an gcoBUFFER object. ** ** gctSIZE_T Bytes ** Number of bytes to reserve. ** ** gctBOOL Aligned ** gcvTRUE if the data needs to be aligned to 64-bit. ** ** OUTPUT: ** ** gctUINT32_PTR ** AddressHints ** Pointer to a variable that receives the current position in the ** state hint array. gcvNULL is allowed. ** ** gctPOINTER * Memory ** Pointer to a variable that will hold the address of location in the ** buffer that has been reserved. */ gceSTATUS gcoBUFFER_Reserve( IN gcoBUFFER Buffer, IN gctSIZE_T Bytes, IN gctBOOL Aligned, OUT gcoCMDBUF * Reserve ) { gceSTATUS status = gcvSTATUS_OK; gcoCMDBUF current; gctSIZE_T alignBytes, bytes; gctUINT offset; gcmHEADER_ARG("Buffer=0x%x Bytes=%lu Aligned=%d Reserve=0x%x", Buffer, Bytes, Aligned, Reserve); /* Verify the arguments. */ gcmVERIFY_OBJECT(Buffer, gcvOBJ_BUFFER); gcmDEBUG_VERIFY_ARGUMENT(Reserve != gcvNULL); /* Get the current command buffer. */ current = Buffer->currentCommandBuffer; /* Compute the number of aligned bytes. */ alignBytes = Aligned ? ( gcmALIGN(current->offset, Buffer->info.alignment) - current->offset ) : 0; /* Compute the number of required bytes. */ bytes = Bytes + alignBytes; if (bytes > current->free) { gcsHAL_INTERFACE iface; if (bytes > Buffer->maxSize - Buffer->totalReserved) { /* This just won't fit! */ gcmFATAL("FATAL: Command of %lu bytes is too big!", Bytes); gcmONERROR(gcvSTATUS_OUT_OF_MEMORY); } /* Sent event to signal when command buffer completes. */ iface.command = gcvHAL_SIGNAL; iface.u.Signal.signal = Buffer->signal [Buffer->currentCommandBufferIndex]; iface.u.Signal.auxSignal = gcvNULL; iface.u.Signal.process = gcoOS_GetCurrentProcessID(); iface.u.Signal.fromWhere = gcvKERNEL_COMMAND; /* Send event. */ gcmONERROR( gcoHARDWARE_CallEvent(&iface)); /* Commit current command buffer. */ gcmONERROR( gcoHARDWARE_Commit()); /* Grab a new command buffer. */ gcmONERROR( gcoBUFFER_GetCMDBUF(Buffer)); /* Get the pointer. */ current = Buffer->currentCommandBuffer; /* Calculate total bytes again. */ alignBytes = 0; bytes = Bytes; } gcmASSERT(current != gcvNULL); gcmASSERT(bytes <= current->free); /* Determine the data offset. */ offset = current->offset + alignBytes; /* Update the last reserved location. */ current->lastReserve = (gctUINT8_PTR) current->logical + offset; current->lastOffset = offset; /* Adjust command buffer size. */ current->offset += bytes; current->free -= bytes; /* Set the result. */ * Reserve = current; /* Success. */ gcmFOOTER(); return gcvSTATUS_OK; OnError: /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoCMDBUF_Construct ** ** Construct a new gcoCMDBUF object. ** ** INPUT: ** ** gcoOS Os ** Pointer to a gcoOS object. ** ** gcoHARDWARE Hardware ** Pointer to a gcoHARDWARE object. ** ** gctSIZE_T Bytes ** Number of bytes for the buffer. ** ** gcsCOMMAND_BUFFER_PTR Info ** Alignment and head/tail information. ** ** OUTPUT: ** ** gcoCMDBUF * CommandBuffer ** Pointer to a variable that will hold the the gcoCMDBUF object ** pointer. */ gceSTATUS gcoCMDBUF_Construct( IN gcoOS Os, IN gcoHARDWARE Hardware, IN gctSIZE_T Bytes, IN gcsCOMMAND_INFO_PTR Info, OUT gcoCMDBUF * CommandBuffer ) { gceSTATUS status; gcoCMDBUF commandBuffer = gcvNULL; gctSIZE_T objectSize; #ifdef __QNXNTO__ gctPHYS_ADDR physical; #else gctPOINTER pointer = gcvNULL; #endif gcmHEADER_ARG("Bytes=%lu Info=0x%x", Bytes, Info); /* Verify the arguments. */ gcmDEBUG_VERIFY_ARGUMENT(Bytes > 0); gcmDEBUG_VERIFY_ARGUMENT(CommandBuffer != gcvNULL); /* Set the size of the object. */ objectSize = gcmSIZEOF(struct _gcoCMDBUF); /* Allocate the gcoCMDBUF object. */ #ifdef __QNXNTO__ /* gcoCMDBUF object needs to be accessible from the kernel; to avoid copying of the data for each access, allocate the object from the kernel non-paged memory. */ gcmONERROR(gcoOS_AllocateNonPagedMemory( gcvNULL, gcvTRUE, &objectSize, &physical, (gctPOINTER *) &commandBuffer )); #else /* Currently in most OS we are able to access the user-side data from the kernel by simple memory mapping, therefore here we allocate the object from the cached user memory. */ gcmONERROR(gcoOS_Allocate(gcvNULL, objectSize, &pointer)); commandBuffer = pointer; #endif /* Reset the command buffer object. */ gcmONERROR(gcoOS_ZeroMemory(commandBuffer, objectSize)); /* Initialize the gcoCMDBUF object. */ commandBuffer->object.type = gcvOBJ_COMMANDBUFFER; commandBuffer->bytes = Bytes; /* Allocate the physical buffer for the command. */ gcmONERROR(gcoOS_AllocateContiguous( gcvNULL, gcvTRUE, &commandBuffer->bytes, &commandBuffer->physical, &commandBuffer->logical )); /* Initialize command buffer. */ commandBuffer->free = commandBuffer->bytes; #if gcdSECURE_USER /* Determine the size of the state array. */ commandBuffer->hintArraySize = Bytes; /* Allocate the state array. */ #ifdef __QNXNTO__ gcmONERROR(gcoOS_AllocateNonPagedMemory( gcvNULL, gcvTRUE, &commandBuffer->hintArraySize, &physical, (gctPOINTER *) &commandBuffer->hintArray )); #else gcmONERROR(gcoOS_Allocate( gcvNULL, commandBuffer->hintArraySize, &pointer )); commandBuffer->hintArray = pointer; #endif /* Initialize the state array tail pointer. */ commandBuffer->hintArrayTail = commandBuffer->hintArray; #endif /* Return pointer to the gcoCMDBUF object. */ *CommandBuffer = commandBuffer; /* Success. */ gcmFOOTER_ARG("*CommandBuffer=0x%x", *CommandBuffer); return gcvSTATUS_OK; OnError: /* Roll back. */ if (commandBuffer != gcvNULL) { if (commandBuffer->logical != gcvNULL) { gcmVERIFY_OK(gcoOS_FreeContiguous( gcvNULL, commandBuffer->physical, commandBuffer->logical, commandBuffer->bytes )); } #if gcdSECURE_USER if (commandBuffer->hintArray != gcvNULL) { #ifdef __QNXNTO__ gcmVERIFY_OK(gcoOS_FreeNonPagedMemory( gcvNULL, commandBuffer->hintArraySize, gcvNULL, commandBuffer->hintArray )); #else gcmVERIFY_OK(gcmOS_SAFE_FREE(gcvNULL, commandBuffer->hintArray)); #endif } #endif #ifdef __QNXNTO__ gcmVERIFY_OK(gcoOS_FreeNonPagedMemory( gcvNULL, objectSize, gcvNULL, commandBuffer )); #else gcmVERIFY_OK(gcmOS_SAFE_FREE(gcvNULL, commandBuffer)); #endif } /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoBUFFER_Construct ** ** Construct a new gcoBUFFER object. ** ** INPUT: ** ** gcoHAL Hal ** Pointer to a gcoHAL object. ** ** gcoHARDWARE Hardware ** Pointer to a gcoHARDWARE object. ** ** gckCONTEXT Context ** Pointer to a gckCONTEXT object. ** ** gctSIZE_T MaxSize ** Maximum size of buffer. ** ** OUTPUT: ** ** gcoBUFFER * Buffer ** Pointer to a variable that will hold the the gcoBUFFER object ** pointer. */ gceSTATUS gcoBUFFER_Construct( IN gcoHAL Hal, IN gcoHARDWARE Hardware, IN gckCONTEXT Context, IN gctSIZE_T MaxSize, OUT gcoBUFFER * Buffer ) { gceSTATUS status; gcoBUFFER buffer = gcvNULL; gctUINT i = 0; gctPOINTER pointer = gcvNULL; gcmHEADER_ARG("Hal=0x%x Hardware=0x%x Context=0x%x MaxSize=%lu", Hal, Hardware, Context, MaxSize); /* Verify the arguments. */ gcmVERIFY_OBJECT(Hal, gcvOBJ_HAL); gcmVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE); gcmDEBUG_VERIFY_ARGUMENT(Buffer != gcvNULL); /*************************************************************************** ** Allocate and reset the gcoBUFFER object. */ gcmONERROR(gcoOS_Allocate( gcvNULL, gcmSIZEOF(struct _gcoBUFFER), &pointer )); buffer = pointer; /* Initialize the gcoBUFFER object. */ buffer->object.type = gcvOBJ_BUFFER; buffer->hal = Hal; buffer->context = Context; /* Maximum size of buffer. */ buffer->size = 0; buffer->maxSize = MaxSize; /* Zero the command buffers. */ for (i = 0; i < gcmCOUNTOF(buffer->commandBuffers); ++i) { buffer->commandBuffers[i] = gcvNULL; buffer->signal[i] = gcvNULL; } /*************************************************************************** ** Query alignment. */ gcmONERROR(gcoHARDWARE_QueryCommandBuffer( &buffer->info.alignment, &buffer->info.reservedHead, &buffer->info.reservedTail )); buffer->totalReserved = buffer->info.reservedHead + buffer->info.reservedTail + buffer->info.alignment; /*************************************************************************** ** Initialize the command buffers. */ for (i = 0; i < gcdCMD_BUFFERS; ++i) { /* Construct a command buffer. */ gcmONERROR(gcoCMDBUF_Construct( gcvNULL, gcvNULL, buffer->maxSize, &buffer->info, &buffer->commandBuffers[i] )); /* Create the signal. */ gcmONERROR(gcoOS_CreateSignal( gcvNULL, gcvFALSE, &buffer->signal[i] )); gcmTRACE_ZONE( gcvLEVEL_INFO, gcvZONE_SIGNAL, "%s(%d): buffer %d signal created 0x%08X", __FUNCTION__, __LINE__, i, buffer->signal[i] ); /* Mark the buffer as available. */ gcmONERROR(gcoOS_Signal( gcvNULL, buffer->signal[i], gcvTRUE\ )); } /* Number of buffers initialized. */ buffer->count = gcdCMD_BUFFERS; /* Grab the first command buffer. */ buffer->currentCommandBuffer = gcvNULL; gcmONERROR(gcoBUFFER_GetCMDBUF(buffer)); /* Return pointer to the gcoBUFFER object. */ *Buffer = buffer; /* Success. */ gcmFOOTER_ARG("*Buffer=0x%x", *Buffer); return gcvSTATUS_OK; OnError: if (buffer != gcvNULL) { gcmVERIFY_OK(gcoBUFFER_FreeObjects(buffer)); } /* Return the status. */ gcmFOOTER(); 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)); }