/******************************************************************************* ** ** gcoBUFFER_Destroy ** ** Destroy an gcoBUFFER object. ** ** INPUT: ** ** gcoBUFFER Buffer ** Pointer to an gcoBUFFER object to delete. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoBUFFER_Destroy( IN gcoBUFFER Buffer ) { gceSTATUS status; gcmHEADER_ARG("Buffer=0x%x", Buffer); /* Verify the arguments. */ gcmVERIFY_OBJECT(Buffer, gcvOBJ_BUFFER); /* Commit buffer before destroying it. */ if (Buffer->size != 0) { /* Commit the command buffers. */ gcmONERROR(gcoHARDWARE_Commit()); /* Stall the hardware. */ gcmONERROR(gcoHARDWARE_Stall()); } /* Free all associated objects. */ gcmONERROR(gcoBUFFER_FreeObjects(Buffer)); OnError: /* Return the status. */ gcmFOOTER(); return status; }
gceSTATUS gcoOS_DisplayBufferRegions( IN HALNativeDisplayType Display, IN HALNativeWindowType Window, IN gctINT NumRects, IN gctINT_PTR Rects ) { screen_buffer_t buf[gcdDISPLAY_BACK_BUFFERS]; int rc; gceSTATUS status = gcvSTATUS_OK; gcmHEADER_ARG("Display=0x%x Window=0x%x NumRects=%d", Display, Window, NumRects); rc = screen_get_window_property_pv((screen_window_t)Window, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)buf); if (rc) { goto OnError; } rc = screen_post_window((screen_window_t)Window, buf[0], NumRects, Rects, 0); if (rc) { goto OnError; } gcmFOOTER_NO(); return status; OnError: status = gcvSTATUS_INVALID_ARGUMENT; gcmFOOTER(); return status; }
/******************************************************************************* ** ** 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; }
/* Write data to profile. */ gceSTATUS gcoPROFILER_Write( IN gcoHAL Hal, IN gctSIZE_T ByteCount, IN gctCONST_POINTER Data ) { gceSTATUS status = gcvSTATUS_OK; gcmHEADER_ARG("ByteCount=%lu Data=0x%x", ByteCount, Data); /* Check if already destroyed. */ if (gcPLS.hal->profiler.enable) { if (gcPLS.hal->profiler.useSocket) { status = gcoOS_Send(gcvNULL, gcPLS.hal->profiler.sockFd, ByteCount, Data, 0); } else { status = gcoOS_Write(gcvNULL, gcPLS.hal->profiler.file, ByteCount, Data); } } gcmFOOTER(); return status; }
gceSTATUS glfCompactNamedObjectList( IN glsCONTEXT_PTR Context, IN glsNAMEDOBJECTLIST_PTR List ) { gceSTATUS status = gcvSTATUS_OK; gcmHEADER_ARG("Context=0x%x List=0x%x", Context, List); do { gceSTATUS last; glsNAMEDOBJECT_PTR wrapper = List->freeList; while (wrapper) { glsNAMEDOBJECT_PTR temp = wrapper; wrapper = wrapper->next; gcmCHECK_STATUS(gcmOS_SAFE_FREE(gcvNULL, temp)); } List->freeList = gcvNULL; } while (gcvFALSE); gcmFOOTER(); return status; }
/* Flush data out. */ gceSTATUS gcoPROFILER_Flush( IN gcoHAL Hal ) { gceSTATUS status = gcvSTATUS_OK; gcmHEADER(); if (gcPLS.hal->profiler.enable) { if (gcPLS.hal->profiler.useSocket) { status = gcoOS_WaitForSend(gcvNULL, gcPLS.hal->profiler.sockFd, 0, 50000); } else { status = gcoOS_Flush(gcvNULL, gcPLS.hal->profiler.file); } } gcmFOOTER(); return status; }
gceSTATUS gcoQUEUE_Destroy( IN gcoQUEUE Queue ) { gceSTATUS status; gcmHEADER_ARG("Queue=0x%x", Queue); /* Verify the arguments. */ gcmVERIFY_OBJECT(Queue, gcvOBJ_QUEUE); #ifndef __QNXNTO__ /* Free any records in the queue. */ while (Queue->head != gcvNULL) { gcsQUEUE_PTR record; /* Unlink the first record from the queue. */ record = Queue->head; Queue->head = record->next; gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, record)); } /* Free any records in the free list. */ while (Queue->freeList != gcvNULL) { gcsQUEUE_PTR record; /* Unlink the first record from the queue. */ record = Queue->freeList; Queue->freeList = record->next; gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, record)); } #else /* Free any records in the queue. */ if ( Queue->records ) { gcmVERIFY_OK(gcoOS_FreeNonPagedMemory(gcvNULL, BUFFER_SIZE, gcvNULL, Queue->records)); } #endif /* Free the queue. */ gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, Queue)); /* Success. */ gcmFOOTER_NO(); return gcvSTATUS_OK; OnError: /* Return the status. */ gcmFOOTER(); return status; }
gceSTATUS vgsMEMORYMANAGER_Construct( IN gcoOS Os, IN gctUINT ItemSize, IN gctUINT Granularity, OUT vgsMEMORYMANAGER_PTR * Manager ) { gceSTATUS status; vgsMEMORYMANAGER_PTR manager = gcvNULL; gcmHEADER_ARG("Os=0x%x ItemSize=0x%x Granularity=0x%x Manager=0x%x", Os, ItemSize, Granularity, Manager); gcmVERIFY_ARGUMENT(ItemSize > 0); gcmVERIFY_ARGUMENT(Granularity > 0); gcmVERIFY_ARGUMENT(Manager != gcvNULL); do { gctUINT itemSize; gctUINT allocationSize; /* Allocate the memory manager structure. */ gcmERR_BREAK(gcoOS_Allocate( Os, gcmSIZEOF(vgsMEMORYMANAGER), (gctPOINTER *) &manager )); /* Determine the size of the item. */ itemSize = gcmSIZEOF(vgsMEMORYITEM) + ItemSize; /* Determine the allocation size. */ allocationSize = gcmSIZEOF(vgsMEMORYITEM) + Granularity * itemSize; /* Initialize the structure. */ manager->os = Os; manager->allocationSize = allocationSize; manager->itemCount = Granularity; manager->itemSize = itemSize; manager->firstAllocated = gcvNULL; manager->firstFree = gcvNULL; #if vgvVALIDATE_MEMORY_MANAGER manager->allocatedCount = 0; manager->maximumAllocated = 0; manager->allocatedBufferCount = 0; #endif /* Set the result pointer. */ * Manager = manager; } while (gcvNULL); gcmFOOTER(); /* Return status. */ return status; }
static gceSTATUS _DeleteBuffer( IN glsCONTEXT_PTR Context, IN gctPOINTER Object ) { gceSTATUS status = gcvSTATUS_OK; gcmHEADER_ARG("Context=0x%x Object=0x%x", Context, Object); do { /* Cast the object. */ glsBUFFER_PTR object = (glsBUFFER_PTR) Object; /* Clear bindings. */ _ClearBindings(Object); /* Clear mapping */ _ClearMapping(Object); /* Destroy index object. */ if (object->index) { gcoINDEX_Destroy(object->index); object->index = gcvNULL; } /* Destroy stream object. */ if (object->stream) { gcoSTREAM_Destroy(object->stream); object->stream = gcvNULL; } #if gcdUSE_TRIANGLE_STRIP_PATCH if (object->subCount > 0) { GLint i; for (i = 0; i < object->subCount; i++) { gcoINDEX_Destroy(object->subs[i].patchIndex); object->subs[i].patchIndex = gcvNULL; } object->subCount = 0; } #endif /* Reset the fields. */ object->size = 0; object->usage = GL_STATIC_DRAW; } while (gcvFALSE); gcmFOOTER(); return status; }
gceSTATUS glfDeleteNamedObject( IN glsCONTEXT_PTR Context, IN glsNAMEDOBJECTLIST_PTR List, gctUINT32 Name ) { gceSTATUS status = gcvSTATUS_OK; gcmHEADER_ARG("Context=0x%x List=0x%x Name=%u", Context, List, Name); do { /* Determine the hash table index. */ gctUINT32 index = Name % glvNAMEDOBJECT_HASHTABLE_SIZE; /* Shortcut to the table entry. */ glsNAMEDOBJECT_PTR* entry = &List->hashTable[index]; /* Keep history. */ glsNAMEDOBJECT_PTR prev = gcvNULL; /* Search from the beginning. */ glsNAMEDOBJECT_PTR curr = *entry; /* Search collided object list. */ while (curr) { if (curr->name == Name) { /* Remove the wrapper from the list of allocated objects. */ if (prev) { prev->next = curr->next; } else { *entry = curr->next; } glfDereferenceNamedObject(Context, curr); break; } /* The current becomes history. */ prev = curr; /* Move to the next one. */ curr = curr->next; } } while (gcvFALSE); gcmFOOTER(); return status; }
static gceSTATUS _CreateBuffer( IN glsCONTEXT_PTR Context, IN gctUINT32 Buffer, OUT glsNAMEDOBJECT_PTR * Wrapper ) { gceSTATUS status; gcmHEADER_ARG("Context=0x%x Buffer=%u Wrapper=0x%x", Context, Buffer, Wrapper); do { glsBUFFER_PTR object; glsCONTEXT_PTR shared; /* Map shared context. */ #if gcdRENDER_THREADS shared = (Context->shared != gcvNULL) ? Context->shared : Context; #else shared = Context; #endif /* Attempt to allocate a new buffer. */ gcmERR_BREAK(glfCreateNamedObject( Context, &shared->bufferList, Buffer, _DeleteBuffer, Wrapper )); /* Get a pointer to the new buffer. */ object = (glsBUFFER_PTR) (*Wrapper)->object; /* Init the buffer to the defaults. */ gcoOS_ZeroMemory(object, sizeof(glsBUFFER)); object->usage = GL_STATIC_DRAW; object->mapped = gcvFALSE; object->bufferMapPointer = gcvNULL; #if gcdUSE_TRIANGLE_STRIP_PATCH object->stripPatchDirty = gcvTRUE; object->subCount = 0; gcoOS_ZeroMemory(object->subs, sizeof(object->subs)); #endif } while (gcvFALSE); gcmFOOTER(); /* Return result. */ return status; }
/******************************************************************************* ** ** gcoDUMP_AddSurface ** ** Allocate a surface. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** gctINT32 Width, Height ** Width and height of the surface. ** ** gceSURF_FORMAT PixelFormat ** Pixel format for the surface. ** ** gctUINT32 Address ** Physical address to be used as a handle for the surface. ** ** gctSIZE_T ByteCount ** Number of bytes inside the surface. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_AddSurface( IN gcoDUMP Dump, IN gctINT32 Width, IN gctINT32 Height, IN gceSURF_FORMAT PixelFormat, IN gctUINT32 Address, IN gctSIZE_T ByteCount ) { gceSTATUS status; gcsDUMP_SURFACE surface; gcmHEADER_ARG("Dump=0x%x Width=%d Height=%d PixelFormat=%d Address=%x " "ByteCount=%d", Dump, Width, Height, PixelFormat, Address, ByteCount); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); gcmVERIFY_ARGUMENT(ByteCount > 0); if (Dump->file == gcvNULL) { /* There is no open dump file. */ gcmFOOTER_NO(); return gcvSTATUS_OK; } do { /* Write the data record. */ surface.type = gcvTAG_SURFACE; surface.address = Address; surface.width = (gctINT16) Width; surface.height = (gctINT16) Height; surface.format = PixelFormat; surface.length = ByteCount; gcmERR_BREAK( gcoOS_Write(gcvNULL, Dump->file, sizeof(surface), &surface)); /* Update the frame length. */ Dump->frameLength += sizeof(surface); /* Update the file length. */ Dump->length += sizeof(surface); } while (gcvFALSE); /* Return the status. */ gcmFOOTER(); return status; }
static gceSTATUS gcoBUFFER_FreeObjects( IN gcoBUFFER Buffer ) { gceSTATUS status; gctUINT i; gcmHEADER_ARG("Buffer=0x%x", Buffer); /* Roll back all command buffers. */ for (i = 0; i < gcmCOUNTOF(Buffer->commandBuffers); i += 1) { if (Buffer->commandBuffers[i] != gcvNULL) { /* Destroy command buffer. */ gcmONERROR(gcoCMDBUF_Destroy(Buffer->commandBuffers[i])); Buffer->commandBuffers[i] = gcvNULL; } if (Buffer->signal[i] != gcvNULL) { /* Destroy signal. */ gcmONERROR(gcoOS_DestroySignal(gcvNULL, Buffer->signal[i])); Buffer->signal[i] = gcvNULL; } } /* Free the object memory. */ gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, Buffer)); /* Success. */ gcmFOOTER(); return gcvSTATUS_OK; OnError: /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoDUMP_DumpData ** ** Dump data the file. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** gceDUMP_TAG Type ** Type of data. ** ** gctUINT32 Address ** Physical address to be used as a handle for the data. ** ** gctSIZE_T ByteCount ** Number of bytes to write. ** ** gctCONST_POINTER Data ** Pointer to the data to write. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_DumpData( IN gcoDUMP Dump, IN gceDUMP_TAG Type, IN gctUINT32 Address, IN gctSIZE_T ByteCount, IN gctCONST_POINTER Data ) { gceSTATUS status; gcsDUMP_DATA header; gcmHEADER_ARG("Dump=0x%x Type=%d Address=%x ByteCount=%d Data=0x%x", Dump, Type, Address, ByteCount, Data); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); gcmVERIFY_ARGUMENT(ByteCount > 0); gcmVERIFY_ARGUMENT(Data != gcvNULL); if (Dump->file == gcvNULL) { /* There is no open dump file. */ gcmFOOTER_NO(); return gcvSTATUS_OK; } do { /* Write the data record. */ header.type = Type; header.length = ByteCount; header.address = Address; gcmERR_BREAK( gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Write the data. */ gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, ByteCount, Data)); /* Update the frame length. */ Dump->frameLength += sizeof(header) + ByteCount; /* Update the file length. */ Dump->length += sizeof(header) + ByteCount; } while (gcvFALSE); /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoDUMP_FrameEnd ** ** Mark the end of a frame. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_FrameEnd( IN gcoDUMP Dump ) { gceSTATUS status; gcsDUMP_DATA header; gctUINT32 pos; gcmHEADER_ARG("Dump=0x%x", Dump); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); if (Dump->file == gcvNULL) { /* There is no open dump file. */ gcmFOOTER_NO(); return gcvSTATUS_OK; } do { /* Get the current position. */ gcmERR_BREAK(gcoOS_GetPos(gcvNULL, Dump->file, &pos)); /* Seek to the beginning of the frame. */ gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, Dump->frameStart)); /* Make sure we got the right byte count. */ gcmASSERT(pos - Dump->frameStart == Dump->frameLength + sizeof(header)); /* Update the frame header. */ header.type = gcvTAG_FRAME; header.length = Dump->frameLength; header.address = ++ Dump->frameCount; gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Seek to the end of the file. */ gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, pos)); /* Mark the frame as ended. */ Dump->frameStart = 0; } while (gcvFALSE); /* Return the status. */ gcmFOOTER(); return status; }
gceSTATUS gcoOS_SetDisplayVirtual( IN HALNativeDisplayType Display, IN HALNativeWindowType Window, IN gctUINT Offset, IN gctINT X, IN gctINT Y ) { screen_buffer_t buf[gcdDISPLAY_BACK_BUFFERS]; int rc; int rects[4]; gceSTATUS status = gcvSTATUS_OK; gcmHEADER_ARG("Display=0x%x Window=0x%x Offset=%u X=%d Y=%d", Display, Window, Offset, X, Y); rects[0] = 0; rects[1] = 0; rc = screen_get_window_property_pv((screen_window_t)Window, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)buf); if (rc) { goto OnError; } rc = screen_get_window_property_iv((screen_window_t)Window, SCREEN_PROPERTY_BUFFER_SIZE, &rects[2]); if (rc) { goto OnError; } rc = screen_post_window((screen_window_t)Window, buf[0], 1, rects, 0); if (rc) { goto OnError; } _ReleaseWindowInfoNode(Window); gcmFOOTER_NO(); return status; OnError: status = gcvSTATUS_INVALID_ARGUMENT; gcmFOOTER(); return status; }
gceSTATUS vgsMEMORYMANAGER_Destroy( IN vgsMEMORYMANAGER_PTR Manager ) { gceSTATUS status; vgsMEMORYITEM_PTR current; vgsMEMORYITEM_PTR next; gcmHEADER_ARG("Manager=0x%x", Manager); /* Verify arguments. */ gcmVERIFY_ARGUMENT(Manager != gcvNULL); /* Assume success. */ status = gcvSTATUS_OK; /* Everything has to be freed. */ #if vgvVALIDATE_MEMORY_MANAGER gcmASSERT(Manager->allocatedCount == 0); #endif /* Destroy all allocated buffers. */ while (Manager->firstAllocated) { /* Get the current buffer. */ current = Manager->firstAllocated; /* Get the next buffer. */ next = current->next; /* Free the current. */ gcmERR_BREAK(gcoOS_Free(Manager->os, current)); /* Advance to the next one. */ Manager->firstAllocated = next; } /* Success? */ if (gcmIS_SUCCESS(status)) { status = gcoOS_Free(Manager->os, Manager); } gcmFOOTER(); /* Return status. */ return status; }
/******************************************************************************* ** ** gcoDUMP_Delete ** ** Mark an address as deleted. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** gctUINT32 Address ** Physical address to delete. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_Delete( IN gcoDUMP Dump, IN gctUINT32 Address ) { gceSTATUS status; gcsDUMP_DATA header; gcmHEADER_ARG("Dump=0x%x Address=%x", Dump, Address); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); if (Dump->file == gcvNULL) { /* There is no open dump file. */ gcmFOOTER_NO(); return gcvSTATUS_OK; } do { /* Write the delete record. */ header.type = gcvTAG_DELETE; header.length = 0; header.address = Address; gcmERR_BREAK( gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Update the frame length. */ Dump->frameLength += sizeof(header); /* Update the file length. */ Dump->length += sizeof(header); } while (gcvFALSE); /* Return the status. */ gcmFOOTER(); return status; }
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; }
/******************************************************************************* ** ** gcoDUMP_FrameBegin ** ** Mark the beginning of a frame. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_FrameBegin( IN gcoDUMP Dump ) { gceSTATUS status; gcsDUMP_DATA header; gcmHEADER_ARG("Dump=0x%x", Dump); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); if ( (Dump->file == gcvNULL) || (Dump->frameStart != 0) ) { /* There is no open dump file. */ gcmFOOTER_NO(); return gcvSTATUS_OK; } do { /* Get the current position. */ gcmERR_BREAK(gcoOS_GetPos(gcvNULL, Dump->file, &Dump->frameStart)); /* Write the frame header. */ header.type = gcvTAG_FRAME; header.length = Dump->frameLength = 0; header.address = 0; gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Update the file length. */ Dump->length += sizeof(header); } while (gcvFALSE); /* Return the status. */ gcmFOOTER(); return status; }
gceSTATUS gcoOS_GetNextDisplayInfoEx( IN HALNativeDisplayType Display, IN HALNativeWindowType Window, IN gctUINT DisplayInfoSize, OUT halDISPLAY_INFO * DisplayInfo ) { int rc; gceSTATUS status = gcvSTATUS_OK; screen_buffer_t buf[gcdDISPLAY_BACK_BUFFERS]; gcmHEADER_ARG("Display=0x%x Window=0x%x DisplayInfoSize=%u", Display, Window, DisplayInfoSize); if ((Window == gcvNULL) || (DisplayInfoSize != sizeof(halDISPLAY_INFO))) { goto OnError; } rc = screen_get_window_property_pv((screen_window_t)Window, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)buf); if (rc) { goto OnError; } rc = screen_post_window((screen_window_t)Window, buf[0], 0, NULL, 0); if (rc) { goto OnError; } status = gcoOS_GetDisplayInfoEx(Display, Window, DisplayInfoSize, DisplayInfo); gcmFOOTER_ARG("*DisplayInfo=0x%x", *DisplayInfo); return status; OnError: status = gcvSTATUS_INVALID_ARGUMENT; gcmFOOTER(); return status; }
gceSTATUS glfDestroyNamedObjectList( IN glsCONTEXT_PTR Context, IN glsNAMEDOBJECTLIST_PTR List ) { gceSTATUS status = gcvSTATUS_OK; gcmHEADER_ARG("Context=0x%x List=0x%x", Context, List); do { gceSTATUS last; gctINT i; /* Free all objects in the free list. */ gcmCHECK_STATUS(glfCompactNamedObjectList(Context, List)); /* Free all existing objects. */ for (i = 0; i < glvNAMEDOBJECT_HASHTABLE_SIZE; i++) { glsNAMEDOBJECT_PTR wrapper = List->hashTable[i]; while (wrapper) { glsNAMEDOBJECT_PTR temp = wrapper; wrapper = wrapper->next; gcmCHECK_STATUS((*temp->deleteObject)(Context, temp->object)); gcmCHECK_STATUS(gcmOS_SAFE_FREE(gcvNULL, temp)); } } } while (gcvFALSE); 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; }
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; }
/******************************************************************************* ** ** 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; }
/******************************************************************************* ** ** 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; }
/******************************************************************************* ** ** gcoDUMP_Control ** ** Control dumping. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** gctSTRING FileName ** If 'FileName' is not gcvNULL, it points to the filename to be used for ** capturing all data. If 'FileName' is gcvNULL, turn off any current ** capturing. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_Control( IN gcoDUMP Dump, IN gctSTRING FileName ) { gceSTATUS status = gcvSTATUS_OK; gcsDUMP_FILE header; gctUINT32 pos; gcmHEADER_ARG("Dump=0x%x FileName=0x%x", Dump, FileName); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); do { if (FileName != gcvNULL) { /* Need to create a new dump file. */ if (Dump->file == gcvNULL) { /* Create the dump file. */ gcmERR_BREAK(gcoOS_Open(gcvNULL, FileName, gcvFILE_CREATE, &Dump->file)); /* Write the file header. */ header.signature = gcvDUMP_FILE_SIGNATURE; header.length = Dump->length = 0; header.frames = Dump->frameCount = 0; gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Frame is not yet started. */ Dump->frameStart = 0; } } else { /* Need to close any current dump file. */ if (Dump->file != gcvNULL) { /* Close any open frame. */ if (Dump->frameStart != 0) { gcoDUMP_FrameEnd(Dump); gcoDUMP_FrameBegin(Dump); } /* Get the current position. */ gcmERR_BREAK(gcoOS_GetPos(gcvNULL, Dump->file, &pos)); /* Seek to the beginnnig of the file. */ gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, 0)); /* Make sure we have the correct size. */ gcmASSERT(pos == Dump->length + sizeof(header)); /* Update the file header. */ header.signature = gcvDUMP_FILE_SIGNATURE; header.length = Dump->length; header.frames = Dump->frameCount; gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Seek to the end of the file. */ gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, pos)); /* Close the file. */ gcmERR_BREAK(gcoOS_Close(gcvNULL, Dump->file)); /* Mark the file as closed. */ Dump->file = gcvNULL; } } } while (gcvFALSE); /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** 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; }
/******************************************************************************* ** ** gcoCMDBUF_Destroy ** ** Destroy a gcoCMDBUF object. ** ** INPUT: ** ** gcoCMDBUF CommandBuffer ** Pointer to an gcoCMDBUF object. ** ** OUTPUT: ** ** None. */ gceSTATUS gcoCMDBUF_Destroy( IN gcoCMDBUF CommandBuffer ) { gceSTATUS status; gcsHAL_INTERFACE iface; gcmHEADER_ARG("CommandBuffer=0x%x", CommandBuffer); /* Verify the object. */ gcmVERIFY_OBJECT(CommandBuffer, gcvOBJ_COMMANDBUFFER); if (CommandBuffer->logical != gcvNULL) { /* Use events to free the buffer. */ iface.command = gcvHAL_FREE_CONTIGUOUS_MEMORY; iface.u.FreeContiguousMemory.bytes = CommandBuffer->bytes; iface.u.FreeContiguousMemory.physical = CommandBuffer->physical; iface.u.FreeContiguousMemory.logical = CommandBuffer->logical; /* Send event. */ gcmONERROR(gcoHARDWARE_CallEvent(&iface)); /* Reset the buffer pointer. */ CommandBuffer->logical = gcvNULL; } #if gcdSECURE_USER if (CommandBuffer->hintArray != gcvNULL) { #ifdef __QNXNTO__ gcmONERROR(gcoOS_FreeNonPagedMemory( gcvNULL, CommandBuffer->hintArraySize, gcvNULL, CommandBuffer->hintArray )); #else gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, CommandBuffer->hintArray)); #endif CommandBuffer->hintArray = CommandBuffer->hintArrayTail = gcvNULL; } #endif /* Free the gcoCMDBUF object. */ #ifdef __QNXNTO__ gcmONERROR(gcoOS_FreeNonPagedMemory( gcvNULL, gcmSIZEOF(struct _gcoCMDBUF), gcvNULL, CommandBuffer )); #else gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, CommandBuffer)); #endif /* Success. */ gcmFOOTER_NO(); return gcvSTATUS_OK; OnError: /* Return the status. */ gcmFOOTER(); return status; }
static gceSTATUS gcoBUFFER_GetCMDBUF( IN gcoBUFFER Buffer ) { gceSTATUS status; gcoCMDBUF command; gctSIZE_T index; gcePIPE_SELECT entryPipe; gcmHEADER_ARG("Buffer=0x%x", Buffer); /* Determine the next command buffer. */ if (Buffer->currentCommandBuffer == gcvNULL) { /* First time - get the first buffer. */ index = 0; /* Select 3D pipe for the first buffer. */ entryPipe = gcvPIPE_3D; } else { /* Get current entry pipe. */ entryPipe = Buffer->currentCommandBuffer->entryPipe; /* Determine the next command buffer index. */ index = (Buffer->currentCommandBufferIndex + 1) % Buffer->count; } /* Test if command buffer is available. */ status = gcoOS_WaitSignal(gcvNULL, Buffer->signal[index], 0); if (status == gcvSTATUS_TIMEOUT) { if (Buffer->count < gcdMAX_CMD_BUFFERS) { do { if (Buffer->commandBuffers[Buffer->count] == gcvNULL) { /* Construct a command buffer. */ gcmERR_BREAK(gcoCMDBUF_Construct( gcvNULL, gcvNULL, Buffer->maxSize, &Buffer->info, &Buffer->commandBuffers[Buffer->count])); } if (Buffer->signal[Buffer->count] == gcvNULL) { /* Create the signal. */ gcmERR_BREAK(gcoOS_CreateSignal( gcvNULL, gcvFALSE, &Buffer->signal[Buffer->count])); gcmTRACE_ZONE( gcvLEVEL_INFO, gcvZONE_SIGNAL, "%s(%d): buffer %d signal created 0x%08X", __FUNCTION__, __LINE__, Buffer->count, Buffer->signal[Buffer->count]); } /* Mark the buffer as available. */ gcmERR_BREAK(gcoOS_Signal(gcvNULL, Buffer->signal[Buffer->count], gcvTRUE)); /* Use the new buffer. */ index = Buffer->count; Buffer->count += 1; gcmTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_BUFFER, "Using %lu command buffers.", Buffer->count); } while (gcvFALSE); } /* Wait for buffer to become available. */ gcmONERROR(gcoOS_WaitSignal(gcvNULL, Buffer->signal[index], gcPLS.hal->timeOut)); } else { gcmONERROR(status); } /* Select new command buffer. */ Buffer->currentCommandBufferIndex = index; Buffer->currentCommandBuffer = Buffer->commandBuffers[index]; /* Grab pointer to current command buffer. */ command = Buffer->currentCommandBuffer; /* Set the entry pipe. */ command->entryPipe = entryPipe; /* Reset command buffer. */ command->startOffset = 0; command->offset = Buffer->info.reservedHead; command->free = command->bytes - Buffer->totalReserved; /* Succees. */ gcmFOOTER_ARG("currentCommandBufferIndex=%d", Buffer->currentCommandBufferIndex); return gcvSTATUS_OK; OnError: /* Return the status. */ gcmFOOTER(); return status; }