gceSTATUS vgfDereferenceObject( vgsCONTEXT_PTR Context, vgsOBJECT_PTR * Object ) { gceSTATUS status = gcvSTATUS_OK; gcmASSERT(Context != gcvNULL); gcmASSERT(Object != gcvNULL); do { /* Get a shortcut to the object. */ vgsOBJECT_PTR object = *Object; /* Already destroyed? */ if (object == gcvNULL) { break; } /* Valid reference count? */ if (object->referenceCount < 1) { gcmFATAL("Invalid reference count found."); status = gcvSTATUS_INVALID_OBJECT; break; } /* Decrement the reference count. */ object->referenceCount--; /* Time to destroy? */ if (object->referenceCount == 0) { vgsOBJECT_LIST_PTR objectList; /* Get a shortcut to the object list. */ objectList = &Context->objectCache->cache[object->type]; /* Call the destructor. */ gcmASSERT(objectList->destructor != gcvNULL); gcmERR_BREAK(objectList->destructor(Context, object)); /* Remove the object from the cache. */ gcmERR_BREAK(vgfObjectCacheRemove(Context, object)); /* Free the object. */ gcmERR_BREAK(gcoOS_Free(Context->os, object)); /* Reset the pointer. */ *Object = gcvNULL; } } while (gcvFALSE); /* Return status. */ return status; }
/******************************************************************************* ** ** 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; }
static gceSTATUS _CLOSE_PATH( vgsPATHWALKER_PTR Destination ) { gceSTATUS status; vgsCONTROL_COORD_PTR coords; do { /* Get a shortcut to the control coordinates. */ coords = Destination->coords; /* Add new command. */ gcmERR_BREAK(vgsPATHWALKER_WriteCommand( Destination, gcvVGCMD_CLOSE )); /* Update the control coordinates. */ coords->lastX = coords->startX; coords->lastY = coords->startY; coords->controlX = coords->startX; coords->controlY = coords->startY; /* Success. */ return gcvSTATUS_OK; } while (gcvFALSE); /* Return status. */ return status; }
gceSTATUS vgsMEMORYMANAGER_Construct( IN gcoOS Os, IN gctUINT ItemSize, IN gctUINT Granularity, OUT vgsMEMORYMANAGER_PTR * Manager ) { gceSTATUS status; vgsMEMORYMANAGER_PTR manager = gcvNULL; gcmHEADER_ARG("Os=0x%x ItemSize=0x%x Granularity=0x%x Manager=0x%x", Os, ItemSize, Granularity, Manager); gcmVERIFY_ARGUMENT(ItemSize > 0); gcmVERIFY_ARGUMENT(Granularity > 0); gcmVERIFY_ARGUMENT(Manager != gcvNULL); do { gctUINT itemSize; gctUINT allocationSize; /* Allocate the memory manager structure. */ gcmERR_BREAK(gcoOS_Allocate( Os, gcmSIZEOF(vgsMEMORYMANAGER), (gctPOINTER *) &manager )); /* Determine the size of the item. */ itemSize = gcmSIZEOF(vgsMEMORYITEM) + ItemSize; /* Determine the allocation size. */ allocationSize = gcmSIZEOF(vgsMEMORYITEM) + Granularity * itemSize; /* Initialize the structure. */ manager->os = Os; manager->allocationSize = allocationSize; manager->itemCount = Granularity; manager->itemSize = itemSize; manager->firstAllocated = gcvNULL; manager->firstFree = gcvNULL; #if vgvVALIDATE_MEMORY_MANAGER manager->allocatedCount = 0; manager->maximumAllocated = 0; manager->allocatedBufferCount = 0; #endif /* Set the result pointer. */ * Manager = manager; } while (gcvNULL); gcmFOOTER(); /* Return status. */ return status; }
static gceSTATUS _SMALL_ARC( vgsPATHWALKER_PTR Destination, gctBOOL CounterClockwise, gctBOOL Relative, gctFLOAT HorRadius, gctFLOAT VerRadius, gctFLOAT RotAngle, gctFLOAT EndX, gctFLOAT EndY ) { gceSTATUS status; vgsPATHWALKER arc; vgsCONTEXT_PTR context; do { /* Close the current subpath. */ vgsPATHWALKER_CloseSubpath(Destination); /* Get a shortcut to the context. */ context = Destination->context; /* Prepare for writing the destination. */ vgsPATHWALKER_InitializeWriter( context, context->pathStorage, &arc, Destination->path ); /* Generate the ARC buffer. */ gcmERR_BREAK(vgfConvertArc( &arc, HorRadius, VerRadius, RotAngle, EndX, EndY, CounterClockwise, gcvFALSE, Relative )); /* Append to the existing buffer. */ vgsPATHWALKER_AppendData( Destination, &arc, 1, 5 ); /* Set the ARC present flag. */ Destination->path->hasArcs = gcvTRUE; /* Success. */ return gcvSTATUS_OK; } while (gcvFALSE); /* Return status. */ return status; }
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_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; }
/******************************************************************************* ** ** 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; }
gceSTATUS _FreeSurface( IN gcsSURFACE * Surface ) { gceSTATUS status = gcvSTATUS_OK; if (Surface == gcvNULL) { return gcvSTATUS_INVALID_ARGUMENT; } do { if (Surface->surface != gcvNULL) { if (Surface->logical != gcvNULL) { gcmERR_BREAK( gcoSURF_Unlock(Surface->surface, Surface->logical)); } gcmERR_BREAK( gcoSURF_Destroy(Surface->surface)); Surface->surface = gcvNULL; Surface->physical = ~0; Surface->logical = gcvNULL; Surface->width = 0; Surface->height = 0; Surface->format = gcvSURF_UNKNOWN; } } while (gcvFALSE); return status; }
gceSTATUS vgsMEMORYMANAGER_Destroy( IN vgsMEMORYMANAGER_PTR Manager ) { gceSTATUS status; vgsMEMORYITEM_PTR current; vgsMEMORYITEM_PTR next; gcmHEADER_ARG("Manager=0x%x", Manager); /* Verify arguments. */ gcmVERIFY_ARGUMENT(Manager != gcvNULL); /* Assume success. */ status = gcvSTATUS_OK; /* Everything has to be freed. */ #if vgvVALIDATE_MEMORY_MANAGER gcmASSERT(Manager->allocatedCount == 0); #endif /* Destroy all allocated buffers. */ while (Manager->firstAllocated) { /* Get the current buffer. */ current = Manager->firstAllocated; /* Get the next buffer. */ next = current->next; /* Free the current. */ gcmERR_BREAK(gcoOS_Free(Manager->os, current)); /* Advance to the next one. */ Manager->firstAllocated = next; } /* Success? */ if (gcmIS_SUCCESS(status)) { status = gcoOS_Free(Manager->os, Manager); } gcmFOOTER(); /* Return status. */ return status; }
/******************************************************************************* ** ** 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; }
static gceSTATUS _MOVE_TO_ABS( vgsPATHWALKER_PTR Destination, gctFLOAT X, gctFLOAT Y ) { gceSTATUS status; vgsCONTROL_COORD_PTR coords; do { /* Get a shortcut to the control coordinates. */ coords = Destination->coords; /* Add new command. */ gcmERR_BREAK(vgsPATHWALKER_WriteCommand( Destination, gcvVGCMD_MOVE )); /* Set the command coordinates. */ Destination->set(Destination, X); Destination->set(Destination, Y); /* Update the control coordinates. */ coords->startX = X; coords->startY = Y; coords->lastX = X; coords->lastY = Y; coords->controlX = X; coords->controlY = Y; /* Success. */ return gcvSTATUS_OK; } while (gcvFALSE); /* Return status. */ return status; }
static gceSTATUS _VLINE_TO_REL( vgsPATHWALKER_PTR Destination, gctFLOAT Y ) { gceSTATUS status; gctFLOAT absY; vgsCONTROL_COORD_PTR coords; do { /* Get a shortcut to the control coordinates. */ coords = Destination->coords; /* Add new command. */ gcmERR_BREAK(vgsPATHWALKER_WriteCommand( Destination, gcvVGCMD_VLINE_EMUL_REL )); /* Set the command coordinates. */ Destination->set(Destination, 0.0f); Destination->set(Destination, Y); /* Determine the absolute coordinate. */ absY = Y + coords->lastY; /* Update the control coordinates. */ coords->lastY = absY; coords->controlX = coords->lastX; coords->controlY = absY; /* Success. */ return gcvSTATUS_OK; } while (gcvFALSE); /* Return status. */ return status; }
/******************************************************************************* ** ** gcoDUMP_Construct ** ** Construct a new gcoDUMP object. ** ** INPUT: ** ** gcoOS Os ** Pointer to an gcoOS object. ** ** gcoOS Hal ** Pointer to an gcoHAL object. ** ** OUTPUT: ** ** gcoDUMP * Dump ** Pointer to a variable receiving the gcoDUMP object pointer. */ gceSTATUS gcoDUMP_Construct( IN gcoOS Os, IN gcoHAL Hal, OUT gcoDUMP * Dump ) { gceSTATUS status; gcoDUMP dump; gctPOINTER pointer = gcvNULL; gcmHEADER_ARG("Os=0x%x Dump=0x%x", Os, Dump); /* Verify the arguments. */ gcmVERIFY_ARGUMENT(Dump != gcvNULL); do { /* Allocate the gcoDUMP structure. */ gcmERR_BREAK(gcoOS_Allocate(Os, sizeof(struct _gcoDUMP), &pointer)); dump = pointer; /* Initialize the gcoDUMP object. */ dump->object.type = gcvOBJ_DUMP; dump->file = gcvNULL; /* Return pointer to the object. */ *Dump = dump; } while (gcvFALSE); /* Return the status. */ gcmFOOTER_ARG("*Dump=0x%x", *Dump); return status; }
gceSTATUS vgfConvertArc( vgsPATHWALKER_PTR Destination, gctFLOAT HorRadius, gctFLOAT VerRadius, gctFLOAT RotAngle, gctFLOAT EndX, gctFLOAT EndY, gctBOOL CounterClockwise, gctBOOL Large, gctBOOL Relative ) { gceSTATUS status; vgsARCCOORDINATES_PTR arcCoords = gcvNULL; do { gctFLOAT endX, endY; gceVGCMD segmentCommand; vgsCONTROL_COORD_PTR coords; /******************************************************************* ** Determine the absolute end point coordinates. */ /* Get a shortcut to the control coordinates. */ coords = Destination->coords; if (Relative) { endX = EndX + coords->lastX; endY = EndY + coords->lastY; } else { endX = EndX; endY = EndY; } /* If both of the radiuses are zeros, make a line out of the arc. */ if ((HorRadius == 0.0f) || (VerRadius == 0.0f) || ((endX == coords->lastX) && (endY == coords->lastY))) { /* Determine the segment command. */ segmentCommand = Relative ? gcvVGCMD_ARC_LINE_REL : gcvVGCMD_ARC_LINE; /* Allocate a new subpath. */ gcmERR_BREAK(vgsPATHWALKER_StartSubpath( Destination, vgmCOMMANDSIZE(2, gctFLOAT), gcePATHTYPE_FLOAT )); /* Write the command. */ gcmERR_BREAK(vgsPATHWALKER_WriteCommand( Destination, segmentCommand )); /* Write the coordinates. */ Destination->set(Destination, EndX); Destination->set(Destination, EndY); } else { VGfloat phi, cosPhi, sinPhi; VGfloat dxHalf, dyHalf; VGfloat x1Prime, y1Prime; VGfloat rx, ry; VGfloat x1PrimeSquare, y1PrimeSquare; VGfloat lambda; VGfloat rxSquare, rySquare; VGint sign; VGfloat sq, signedSq; VGfloat cxPrime, cyPrime; VGfloat theta1, thetaSpan; VGint segs; VGfloat theta, ax, ay, x, y; VGfloat controlX, controlY, anchorX, anchorY; VGfloat lastX, lastY; gctUINT bufferSize; /******************************************************************* ** Converting. */ phi = RotAngle / 180.0f * vgvPI; cosPhi = gcmCOSF(phi); sinPhi = gcmSINF(phi); if (Relative) { dxHalf = - EndX / 2.0f; dyHalf = - EndY / 2.0f; } else { dxHalf = (coords->lastX - endX) / 2.0f; dyHalf = (coords->lastY - endY) / 2.0f; } x1Prime = cosPhi * dxHalf + sinPhi * dyHalf; y1Prime = -sinPhi * dxHalf + cosPhi * dyHalf; rx = gcmFABSF(HorRadius); ry = gcmFABSF(VerRadius); x1PrimeSquare = x1Prime * x1Prime; y1PrimeSquare = y1Prime * y1Prime; lambda = x1PrimeSquare / (rx * rx) + y1PrimeSquare / (ry * ry); if (lambda > 1.0f) { rx *= gcmSQRTF(lambda); ry *= gcmSQRTF(lambda); } rxSquare = rx * rx; rySquare = ry * ry; sign = (Large == CounterClockwise) ? -1 : 1; sq = ( rxSquare * rySquare - rxSquare * y1PrimeSquare - rySquare * x1PrimeSquare ) / ( rxSquare * y1PrimeSquare + rySquare * x1PrimeSquare ); signedSq = sign * ((sq < 0) ? 0 : gcmSQRTF(sq)); cxPrime = signedSq * (rx * y1Prime / ry); cyPrime = signedSq * -(ry * x1Prime / rx); theta1 = _Angle(1, 0, (x1Prime - cxPrime) / rx, (y1Prime - cyPrime) / ry); theta1 = gcmFMODF(theta1, 2 * vgvPI); thetaSpan = _Angle(( x1Prime - cxPrime) / rx, ( y1Prime - cyPrime) / ry, (-x1Prime - cxPrime) / rx, (-y1Prime - cyPrime) / ry); if (!CounterClockwise && (thetaSpan > 0)) { thetaSpan -= 2 * vgvPI; } else if (CounterClockwise && (thetaSpan < 0)) { thetaSpan += 2 * vgvPI; } thetaSpan = gcmFMODF(thetaSpan, 2 * vgvPI); /******************************************************************* ** Drawing. */ segs = (VGint) (gcmCEILF(gcmFABSF(thetaSpan) / (45.0f / 180.0f * vgvPI))); gcmASSERT(segs > 0); theta = thetaSpan / segs; ax = coords->lastX - gcmCOSF(theta1) * rx; ay = coords->lastY - gcmSINF(theta1) * ry; /* Determine the segment command. */ segmentCommand = Relative ? gcvVGCMD_ARC_QUAD_REL : gcvVGCMD_ARC_QUAD; /* Determine the size of the buffer required. */ bufferSize = (1 + 2 * 2) * gcmSIZEOF(gctFLOAT) * segs; /* Allocate a new subpath. */ gcmERR_BREAK(vgsPATHWALKER_StartSubpath( Destination, bufferSize, gcePATHTYPE_FLOAT )); /* Set initial last point. */ lastX = coords->lastX; lastY = coords->lastY; while (segs-- > 0) { theta1 += theta; controlX = ax + gcmCOSF(theta1 - (theta / 2.0f)) * rx / gcmCOSF(theta / 2.0f); controlY = ay + gcmSINF(theta1 - (theta / 2.0f)) * ry / gcmCOSF(theta / 2.0f); anchorX = ax + gcmCOSF(theta1) * rx; anchorY = ay + gcmSINF(theta1) * ry; if (RotAngle != 0) { x = coords->lastX + cosPhi * (controlX - coords->lastX) - sinPhi * (controlY - coords->lastY); y = coords->lastY + sinPhi * (controlX - coords->lastX) + cosPhi * (controlY - coords->lastY); controlX = x; controlY = y; x = coords->lastX + cosPhi * (anchorX - coords->lastX) - sinPhi * (anchorY - coords->lastY); y = coords->lastY + sinPhi * (anchorX - coords->lastX) + cosPhi * (anchorY - coords->lastY); anchorX = x; anchorY = y; } if (segs == 0) { /* Use end point directly to avoid accumulated errors. */ anchorX = endX; anchorY = endY; } /* Adjust relative coordinates. */ if (Relative) { VGfloat nextLastX = anchorX; VGfloat nextLastY = anchorY; controlX -= lastX; controlY -= lastY; anchorX -= lastX; anchorY -= lastY; lastX = nextLastX; lastY = nextLastY; } /* Write the command. */ gcmERR_BREAK(vgsPATHWALKER_WriteCommand( Destination, segmentCommand )); /* Set the coordinates. */ Destination->set(Destination, controlX); Destination->set(Destination, controlY); Destination->set(Destination, anchorX); Destination->set(Destination, anchorY); } } /* Store ARC coordinates. */ gcmERR_BREAK(vgsMEMORYMANAGER_Allocate( Destination->arcCoordinates, (gctPOINTER *) &arcCoords )); arcCoords->large = Large; arcCoords->counterClockwise = CounterClockwise; arcCoords->horRadius = HorRadius; arcCoords->verRadius = VerRadius; arcCoords->rotAngle = RotAngle; arcCoords->endX = EndX; arcCoords->endY = EndY; /* Store the pointer to ARC coordinates. */ Destination->currPathData->extraManager = Destination->arcCoordinates; Destination->currPathData->extra = arcCoords; /* Update the control coordinates. */ coords->lastX = endX; coords->lastY = endY; coords->controlX = endX; coords->controlY = endY; /* Success. */ return gcvSTATUS_OK; } while (gcvFALSE); /* Roll back. */ vgsPATHWALKER_Rollback(Destination); /* Return status. */ return status; }
gceSTATUS vgsMEMORYMANAGER_Allocate( IN vgsMEMORYMANAGER_PTR Manager, OUT gctPOINTER * Pointer ) { gceSTATUS status; vgsMEMORYITEM_PTR firstFree; gcmHEADER_ARG("Manager=0x%x Pointer=0x%x", Manager, Pointer); /* Verify arguments. */ gcmVERIFY_ARGUMENT(Manager != gcvNULL); gcmVERIFY_ARGUMENT(Pointer != gcvNULL); /* Get the first free. */ firstFree = Manager->firstFree; /* Are there free items? */ if (firstFree != gcvNULL) { /* Set the result. */ * Pointer = firstFree + 1; /* Remove from the free list. */ Manager->firstFree = firstFree->next; /* Update allocated items count. */ #if vgvVALIDATE_MEMORY_MANAGER Manager->allocatedCount += 1; if ((gctUINT) Manager->allocatedCount > Manager->maximumAllocated) { Manager->maximumAllocated = Manager->allocatedCount; } #endif /* Success. */ gcmFOOTER_ARG("*Pointer=0x%x", *Pointer); return gcvSTATUS_OK; } /* No free items available. */ do { vgsMEMORYITEM_PTR newBuffer; gctUINT i, itemCount; gctUINT itemSize; /* Allocate a new buffer. */ gcmERR_BREAK(gcoOS_Allocate( Manager->os, Manager->allocationSize, (gctPOINTER) &newBuffer )); /* Link in. */ newBuffer->next = Manager->firstAllocated; Manager->firstAllocated = newBuffer; /* Set the result. */ * Pointer = newBuffer + 2; /* Update allocated items count. */ #if vgvVALIDATE_MEMORY_MANAGER Manager->allocatedCount += 1; Manager->allocatedBufferCount += 1; if ((gctUINT) Manager->allocatedCount > Manager->maximumAllocated) { Manager->maximumAllocated = Manager->allocatedCount; } #endif /* Get the number of items per allocation. */ itemCount = Manager->itemCount; /* Get the item size. */ itemSize = Manager->itemSize; /* Determine the first free item. */ firstFree = (vgsMEMORYITEM_PTR) ( (gctUINT8_PTR) (newBuffer + 1) + itemSize ); /* Populate the new buffer. */ for (i = 1; i < itemCount; i++) { /* Add to the free item list. */ firstFree->next = Manager->firstFree; Manager->firstFree = firstFree; /* Advance to the next item. */ firstFree = (vgsMEMORYITEM_PTR) ( (gctUINT8_PTR) firstFree + itemSize ); } } while (gcvFALSE); gcmFOOTER(); /* Return status. */ return status; }
/******************************************************************************* ** ** _WorkaroundForFilterBlit ** ** Workaround for the dirty region issue of filter blit. ** It only exists for old GC300 before 2.0.2 (included). ** ** INPUT: ** ** gctHAL Hal ** Pointer to HAL. ** ** OUTPUT: ** ** Nothing. */ static gceSTATUS _WorkaroundForFilterBlit( IN gcoHAL Hal ) { gceSTATUS status; gcoSURF srcSurf = gcvNULL; gcsRECT srcRect; gcoSURF dstSurf = gcvNULL; gcsRECT dstRect; do { gcmERR_BREAK(gcoSURF_Construct( gcvNULL, 256, 256, 1, gcvSURF_BITMAP, gcvSURF_A8R8G8B8, gcvPOOL_DEFAULT, &srcSurf )); gcmERR_BREAK(gcoSURF_Construct( gcvNULL, 256, 256, 1, gcvSURF_BITMAP, gcvSURF_A8R8G8B8, gcvPOOL_DEFAULT, &dstSurf )); srcRect.left = 0; srcRect.top = 0; srcRect.right = 64; srcRect.bottom = 16; dstRect.left = 0; dstRect.top = 0; dstRect.right = 128; dstRect.bottom = 32; gcmERR_BREAK(gcoSURF_FilterBlit( srcSurf, dstSurf, &srcRect, &dstRect, gcvNULL )); gcmERR_BREAK(gcoSURF_Destroy(srcSurf)); srcSurf = gcvNULL; gcmERR_BREAK(gcoSURF_Destroy(dstSurf)); dstSurf = gcvNULL; } while(gcvFALSE); if (gcmIS_ERROR(status)) { gcmTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_HAL, "Failed to workarond for GC300."); if (srcSurf) { gcmVERIFY_OK(gcoSURF_Destroy(srcSurf)); } if (dstSurf) { gcmVERIFY_OK(gcoSURF_Destroy(dstSurf)); } } return status; }
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; }
static gceSTATUS _DereferenceObjectCache( vgsCONTEXT_PTR Context, vgsOBJECT_CACHE_PTR * ObjectCache ) { /* Define the result and assume success. */ gceSTATUS status = gcvSTATUS_OK; do { vgsOBJECT_PTR object; vgsOBJECT_LIST_PTR objectList; /* Get a shortcut to the object cache. */ vgsOBJECT_CACHE_PTR objectCache = *ObjectCache; /* Existing object cache? */ if (objectCache == gcvNULL) { break; } /* Valid reference count? */ if (objectCache->referenceCount < 1) { gcmFATAL("Invalid reference count found.\n"); status = gcvSTATUS_INVALID_OBJECT; break; } /* Decrement the counter. */ objectCache->referenceCount--; /* Time to destroy? */ if (objectCache->referenceCount == 0) { gctUINT i; /* Delete objects that are still in the cache. */ for (i = 0; i < vgvOBJECTTYPE_COUNT; i++) { gctUINT32 index; /* Get the current object list. */ objectList = &objectCache->cache[i]; for (index = 0; index < vgvNAMED_OBJECTS_HASH; index++) { /* Are there objects in the list? */ if (objectList->head[index] != gcvNULL) { gcmTRACE( gcvLEVEL_ERROR, "%s (%d): object cache %d still has objects in it.\n", __FUNCTION__, __LINE__, i ); /* Delete the objects. */ while (objectList->head[index]) { /* Copy the head object. */ object = objectList->head[index]; /* Dereference it. */ gcmERR_BREAK(vgfDereferenceObject( Context, &object )); } } } /* Error? */ if (gcmIS_ERROR(status)) { break; } } /* Error? */ if (gcmIS_ERROR(status)) { break; } /* Allocate the context structure. */ gcmERR_BREAK(gcoOS_Free( Context->os, (gctPOINTER *) objectCache )); /* Reset the object. */ *ObjectCache = gcvNULL; } } while (gcvFALSE); /* Return status. */ return status; }
static gceSTATUS _MonoBlit( IN gcsCOPYBIT_CONTEXT * Context, IN gctUINT32 SourcePhysical, IN gctUINT32 SourceStride, IN gceSURF_FORMAT SourceFormat, IN gctUINT32 DestPhysical, IN gctUINT32 DestStride, IN gceSURF_FORMAT DestFormat, IN gcsRECT * Rect ) { gceSTATUS status = gcvSTATUS_OK; do { if ((Context->perpixelAlpha) || (Context->planeAlpha != 0xFF) ) { gcmERR_BREAK( gco2D_DisableAlphaBlend(Context->engine)); /* PlaneAlpha dirty. */ Context->dirty.s.alphaKey = 1; } if ((Context->transform == COPYBIT_TRANSFORM_ROT_180) || (Context->transform == COPYBIT_TRANSFORM_FLIP_H) || (Context->transform == COPYBIT_TRANSFORM_FLIP_V) ) { gcmERR_BREAK( gco2D_SetBitBlitMirror(Context->engine, gcvFALSE, gcvFALSE)); /* Transform dirty. */ Context->dirty.s.transformKey = 1; } gcmERR_BREAK( gco2D_SetColorSource(Context->engine, SourcePhysical, SourceStride, SourceFormat, gcvSURF_0_DEGREE, 0, gcvFALSE, gcvSURF_OPAQUE, 0)); gcmERR_BREAK( gco2D_SetSource(Context->engine, Rect)); gcmERR_BREAK( gco2D_SetTarget(Context->engine, DestPhysical, DestStride, gcvSURF_0_DEGREE, 0)); gcmERR_BREAK( gco2D_SetClipping(Context->engine, Rect)); gcmERR_BREAK( gco2D_Blit(Context->engine, 1, Rect, 0xCC, 0xCC, DestFormat)); } while (gcvFALSE); return status; }
static gceSTATUS _ReferenceObjectCache( vgsCONTEXT_PTR Context, vgsOBJECT_CACHE_PTR * ObjectCache ) { gceSTATUS status, last; vgsOBJECT_CACHE_PTR objectCache = gcvNULL; do { /* Has the object cache been created? */ if (*ObjectCache == gcvNULL) { static vgtSET_OBJECT_LIST initList[] = { vgfSetPathObjectList, vgfSetImageObjectList, vgfSetMaskObjectList, vgfSetFontObjectList, vgfSetPaintObjectList }; gctUINT i; /* Allocate the context structure. */ gcmERR_BREAK(gcoOS_Allocate( Context->os, gcmSIZEOF(vgsOBJECT_CACHE), (gctPOINTER *) &objectCache )); gcmERR_BREAK(gcoOS_ZeroMemory( objectCache, gcmSIZEOF(vgsOBJECT_CACHE))); /* Initialize the object. */ objectCache->loHandle = ~0; objectCache->hiHandle = 0; objectCache->referenceCount = 0; /* Initialize object arrays. */ for (i = 0; i < gcmCOUNTOF(initList); i++) { initList[i] (&objectCache->cache[i]); } /* Set the result pointer. */ *ObjectCache = objectCache; } /* Increment the counter. */ (*ObjectCache)->referenceCount++; /* Success. */ return gcvSTATUS_OK; } while (gcvFALSE); /* Roll back. */ if (objectCache != gcvNULL) { gcmCHECK_STATUS(gcoOS_Free(Context->os, objectCache)); } /* Return status. */ return status; }
static gceSTATUS _UploadStates( IN gcsCOPYBIT_CONTEXT * Context ) { gceSTATUS status = gcvSTATUS_OK; do { if (Context->dirty.i == 0) { /* Done. */ break; } /* rotationDeg. */ if (Context->dirty.s.rotationDegKey) { /* TODO: rotationDeg. */ Context->dirty.s.rotationDegKey = 0; } /* planeAlpha. */ if (Context->dirty.s.alphaKey) { /* Setup alpha blending. */ if ((Context->perpixelAlpha) || (Context->planeAlpha != 0xFF) ) { gcmERR_BREAK( gco2D_EnableAlphaBlend(Context->engine, Context->planeAlpha, Context->planeAlpha, gcvSURF_PIXEL_ALPHA_STRAIGHT, gcvSURF_PIXEL_ALPHA_STRAIGHT, gcvSURF_GLOBAL_ALPHA_SCALE, gcvSURF_GLOBAL_ALPHA_ON, gcvSURF_BLEND_STRAIGHT, gcvSURF_BLEND_INVERSED, gcvSURF_COLOR_STRAIGHT, gcvSURF_COLOR_STRAIGHT)); } else { gcmERR_BREAK( gco2D_DisableAlphaBlend(Context->engine)); } Context->dirty.s.alphaKey = 0; } /* Dither. */ if (Context->dirty.s.ditherKey) { /* TODO: Dither. */ Context->dirty.s.ditherKey = 0; } /* Transform. */ if (Context->dirty.s.transformKey) { Context->dstRotation = gcvSURF_0_DEGREE; Context->srcRotation = gcvSURF_0_DEGREE; gctBOOL horizonMirror = gcvFALSE; gctBOOL verticalMirror = gcvFALSE; /* Setup transform */ switch(Context->transform) { case COPYBIT_TRANSFORM_FLIP_H: horizonMirror = gcvTRUE; break; case COPYBIT_TRANSFORM_FLIP_V: verticalMirror = gcvTRUE; break; case COPYBIT_TRANSFORM_ROT_90: Context->dstRotation = gcvSURF_90_DEGREE; break; case COPYBIT_TRANSFORM_ROT_180: horizonMirror = gcvTRUE; verticalMirror = gcvTRUE; break; case COPYBIT_TRANSFORM_ROT_270: Context->srcRotation = gcvSURF_90_DEGREE; break; default: break; } gcmERR_BREAK( gco2D_SetBitBlitMirror(Context->engine, horizonMirror, verticalMirror)); Context->dirty.s.transformKey = 0; } /* Blur. */ if (Context->dirty.s.blurKey) { /* TODO: Blur. */ Context->dirty.s.blurKey = 0; } } while (gcvFALSE); return status; }
gceSTATUS _StretchBlitPE1x( IN gcsCOPYBIT_CONTEXT * Context, IN struct copybit_image_t const * Dest, IN struct copybit_image_t const * Source, IN struct copybit_rect_t const * DestRect, IN struct copybit_rect_t const * SourceRect, IN struct copybit_region_t const * Clip) { gceSTATUS status = gcvSTATUS_OK; gceSURF_FORMAT siFormat; gceSURF_FORMAT diFormat; gctUINT32 diPhysical = ~0; gctUINT32 diAlignedWidth; gctUINT32 diAlignedHeight; gctINT diStride; gcsRECT srcRect; gcsRECT dstRect; copybit_rect_t rect; gctUINT32 srcPhysical = ~0; gctINT srcStride; gctUINT32 srcAlignedWidth; gctUINT32 srcAlignedHeight; gceSURF_FORMAT srcFormat; gctUINT32 dstPhysical = ~0; gctINT dstStride; gctUINT32 dstAlignedWidth; gctUINT32 dstAlignedHeight; gceSURF_FORMAT dstFormat; gctBOOL stretch = gcvFALSE; gctBOOL yuvFormat = gcvFALSE; gctBOOL perpixelAlpha; gc_private_handle_t* dsthnd = (gc_private_handle_t *) Dest->handle; gc_private_handle_t* srchnd = (gc_private_handle_t *) Source->handle; LOGV("Blit from Source hnd=%p, to Dest hnd=%p", srchnd, dsthnd); if (gc_private_handle_t::validate(dsthnd) < 0) { gcmTRACE(gcvLEVEL_ERROR, "Invalid hnd in funciton %s", __func__); return gcvSTATUS_INVALID_ARGUMENT; } siFormat = (gceSURF_FORMAT) srchnd->format; diFormat = (gceSURF_FORMAT) dsthnd->format; if ((siFormat == gcvSURF_UNKNOWN) || (diFormat == gcvSURF_UNKNOWN) ) { gcmTRACE(gcvLEVEL_ERROR, "Image format not support in copybit!"); return gcvSTATUS_INVALID_ARGUMENT; } /* Convert to supported Source format. */ siFormat = (siFormat == gcvSURF_A8B8G8R8) ? gcvSURF_A8R8G8B8 : siFormat; siFormat = (siFormat == gcvSURF_X8B8G8R8) ? gcvSURF_X8R8G8B8 : siFormat; /* Convert to supported Dest format. */ diFormat = (diFormat == gcvSURF_A8B8G8R8) ? gcvSURF_A8R8G8B8 : diFormat; diFormat = (diFormat == gcvSURF_X8B8G8R8) ? gcvSURF_X8R8G8B8 : diFormat; do { srcPhysical = srchnd->phys; gcoSURF_GetAlignedSize((gcoSURF) srchnd->surface, &srcAlignedWidth, &srcAlignedHeight, &srcStride); diPhysical = dsthnd->phys; gcoSURF_GetAlignedSize((gcoSURF) dsthnd->surface, &diAlignedWidth, &diAlignedHeight, &diStride); if ((((gcoSURF)srchnd->surface)->info.type == gcvSURF_BITMAP) && !(srchnd->flags & gc_private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { /* Clean the CPU cache. Source would've been rendered by the CPU. */ gcmERR_BREAK( gcoSURF_CPUCacheOperation( (gcoSURF) srchnd->surface, gcvCACHE_CLEAN ) ); } perpixelAlpha = _HasAlpha(siFormat) && (dsthnd->flags & gc_private_handle_t::PRIV_FLAGS_FRAMEBUFFER) && !(srchnd->flags & gc_private_handle_t::PRIV_FLAGS_FRAMEBUFFER); if (Context->perpixelAlpha != perpixelAlpha) { Context->perpixelAlpha = perpixelAlpha; if (Context->planeAlpha == 0xff) { Context->dirty.s.alphaKey = 1; } } /* Need temp surface if source has alpha channel, but dest not. */ Context->needAlphaDest = Context->perpixelAlpha && !_HasAlpha(diFormat); if (Context->needAlphaDest) { gcsRECT tempRect; tempRect.left = gcmMAX(0, DestRect->l); tempRect.top = gcmMAX(0, DestRect->t); tempRect.right = gcmMIN((int32_t) Dest->w, DestRect->r); tempRect.bottom = gcmMIN((int32_t) Dest->h, DestRect->b); gcmERR_BREAK( _FitSurface(Context, &Context->alphaDest, Dest->w, Dest->h)); if (Context->alphaDest.surface == gcvNULL) { gcmTRACE(gcvLEVEL_ERROR, "fail to construct tmp surface for per_pixel_alpha"); break; } /* Copy dest surface to temp surface. */ gcmERR_BREAK( _MonoBlit(Context, diPhysical, diStride, diFormat, Context->alphaDest.physical, Context->alphaDest.stride, Context->alphaDest.format, &tempRect)); } gcmERR_BREAK( _UploadStates(Context)); if (Context->needAlphaDest) { dstPhysical = Context->alphaDest.physical; dstStride = Context->alphaDest.stride; dstAlignedWidth = Context->alphaDest.alignedWidth; dstAlignedHeight = Context->alphaDest.alignedHeight; dstFormat = Context->alphaDest.format; } else { dstPhysical = diPhysical; dstStride = diStride; dstAlignedWidth = diAlignedWidth; dstAlignedHeight = diAlignedHeight; dstFormat = diFormat; } srcFormat = siFormat; if (Context->transform == COPYBIT_TRANSFORM_ROT_270) { srcRect.left = SourceRect->t; srcRect.top = Source->w - SourceRect->r; srcRect.right = SourceRect->b; srcRect.bottom = Source->w - SourceRect->l; } else { srcRect.left = SourceRect->l; srcRect.top = SourceRect->t; srcRect.right = SourceRect->r; srcRect.bottom = SourceRect->b; } if (Context->transform == COPYBIT_TRANSFORM_ROT_90) { dstRect.left = DestRect->t; dstRect.top = Dest->w - DestRect->r; dstRect.right = DestRect->b; dstRect.bottom = Dest->w - DestRect->l; } else { dstRect.left = DestRect->l; dstRect.top = DestRect->t; dstRect.right = DestRect->r; dstRect.bottom = DestRect->b; } /* Check yuv format. */ yuvFormat = (srcFormat == gcvSURF_YUY2 || srcFormat == gcvSURF_UYVY); stretch = (srcRect.right - srcRect.left) != (dstRect.right - dstRect.left) || (srcRect.bottom - srcRect.top) != (dstRect.bottom - dstRect.top); /* Upload stretch factor. */ if (stretch) { int hFactor; int vFactor; if ((dstRect.right-dstRect.left) > 1 && (dstRect.bottom-dstRect.top) > 1) { hFactor = ((srcRect.right - srcRect.left - 1) << 16) / (dstRect.right - dstRect.left - 1); vFactor = ((srcRect.bottom - srcRect.top - 1) << 16) / (dstRect.bottom - dstRect.top - 1); } else { hFactor = 0; vFactor = 0; } gcmERR_BREAK( gco2D_SetStretchFactors(Context->engine, hFactor, vFactor)); } /* Prepare source and target for normal blit. */ gcmERR_BREAK( gco2D_SetColorSource(Context->engine, srcPhysical, srcStride, srcFormat, Context->srcRotation, srcAlignedWidth, gcvFALSE, gcvSURF_OPAQUE, 0)); gcmERR_BREAK( gco2D_SetSource(Context->engine, &srcRect)); gcmERR_BREAK( gco2D_SetTarget(Context->engine, dstPhysical, dstStride, Context->dstRotation, dstAlignedWidth)); gcsRECT srcRectBackup = srcRect; gcsRECT dstRectBackup = dstRect; /* Go though all clip rectangles. */ while (Clip->next(Clip, &rect)) { gcsRECT clipRect; srcRect = srcRectBackup; dstRect = dstRectBackup; if (Context->transform == COPYBIT_TRANSFORM_ROT_90) { clipRect.left = rect.t; clipRect.top = Dest->w - rect.r; clipRect.right = rect.b; clipRect.bottom = Dest->w - rect.l; } else if (Context->transform == COPYBIT_TRANSFORM_ROT_180) { float hfactor = (float) (SourceRect->r - SourceRect->l) / (DestRect->r - DestRect->l); float vfactor = (float) (SourceRect->b - SourceRect->t) / (DestRect->b - DestRect->t); /* Intersect. */ clipRect.left = gcmMAX(dstRect.left, rect.l); clipRect.top = gcmMAX(dstRect.top, rect.t); clipRect.right = gcmMIN(dstRect.right, rect.r); clipRect.bottom = gcmMIN(dstRect.bottom, rect.b); /* Adjust src rectangle. */ srcRect.left += (int) ((dstRect.right - clipRect.right) * hfactor); srcRect.top += (int) ((dstRect.bottom - clipRect.bottom) * vfactor); srcRect.right -= (int) ((clipRect.left - dstRect.left) * hfactor); srcRect.bottom -= (int) ((clipRect.top - dstRect.top) * vfactor); /* Set dstRect to clip rectangle. */ dstRect = clipRect; if ((srcRect.left != srcRectBackup.left) || (srcRect.right != srcRectBackup.right) || (srcRect.top != srcRectBackup.top) || (srcRect.bottom != srcRectBackup.bottom) ) { gcmERR_BREAK( gco2D_SetSource(Context->engine, &srcRect)); } } else { clipRect.left = rect.l; clipRect.top = rect.t; clipRect.right = rect.r; clipRect.bottom = rect.b; } /* Clamp clip rectangle. */ if (clipRect.right > dstRect.right) clipRect.right = dstRect.right; if (clipRect.bottom > dstRect.bottom) clipRect.bottom = dstRect.bottom; if (clipRect.left < dstRect.left) clipRect.left = dstRect.left; if (clipRect.top < dstRect.top) clipRect.top = dstRect.top; gcmERR_BREAK( gco2D_SetClipping(Context->engine, &clipRect)); if (yuvFormat) { /* TODO: FilterBlit does not support rotation before PE20. */ /* Video filter blit */ /* 1. SetClipping() has no effect for FilterBlit() * so we use dstSubRect to realize clipping effect * 2. Only FilterBlit support yuv format covertion. */ gcsRECT dstSubRect; int dstWidth = dstRect.right - dstRect.left; int dstHeight = dstRect.bottom - dstRect.top; int clipWidth = clipRect.right - clipRect.left; int clipHeight = clipRect.bottom - clipRect.top; dstSubRect.left = clipRect.left - dstRect.left; dstSubRect.top = clipRect.top - dstRect.top; dstSubRect.right = dstWidth < clipWidth ? dstSubRect.left + dstWidth : dstSubRect.left + clipWidth; dstSubRect.bottom = dstHeight < clipHeight ? dstSubRect.top + dstHeight : dstSubRect.top + clipHeight; gcmERR_BREAK( gco2D_SetKernelSize(Context->engine, gcdFILTER_BLOCK_SIZE, gcdFILTER_BLOCK_SIZE)); gcmERR_BREAK( gco2D_SetFilterType(Context->engine, gcvFILTER_SYNC)); gcmERR_BREAK( gco2D_FilterBlit(Context->engine, srcPhysical, srcStride, 0, 0, 0, 0, srcFormat, Context->srcRotation, srcAlignedWidth, &srcRect, dstPhysical, dstStride, dstFormat, Context->dstRotation, dstAlignedWidth, &dstRect, &dstSubRect)); } else if (Context->blur) { /* TODO: FilterBlit does not support rotation before PE20. */ gcsRECT dstSubRect; dstSubRect.left = 0; dstSubRect.top = 0; dstSubRect.right = dstRect.right - dstRect.left; dstSubRect.bottom = dstRect.bottom - dstRect.top; /* Blur blit. */ gcmERR_BREAK( gco2D_SetKernelSize(Context->engine, gcdFILTER_BLOCK_SIZE, gcdFILTER_BLOCK_SIZE)); gcmERR_BREAK( gco2D_SetFilterType(Context->engine, gcvFILTER_BLUR)); gcmERR_BREAK( gco2D_FilterBlit(Context->engine, srcPhysical, srcStride, 0, 0, 0, 0, srcFormat, gcvSURF_0_DEGREE, srcAlignedWidth, &srcRect, dstPhysical, dstStride, dstFormat, gcvSURF_0_DEGREE, dstAlignedWidth, &dstRect, &dstSubRect)); gcmERR_BREAK( gco2D_FilterBlit(Context->engine, dstPhysical, dstStride, 0, 0, 0, 0, dstFormat, gcvSURF_0_DEGREE, dstAlignedWidth, &dstRect, dstPhysical, dstStride, dstFormat, gcvSURF_0_DEGREE, dstAlignedWidth, &dstRect, &dstSubRect)); /* TODO: surfaceflinger set blur issue. */ Context->blur = COPYBIT_DISABLE; } else if (stretch == gcvFALSE) { /* BitBlit. */ gcmERR_BREAK( gco2D_Blit(Context->engine, 1, &dstRect, 0xCC, 0xCC, dstFormat)); } else { /* Normal stretch blit. */ gcmERR_BREAK( gco2D_StretchBlit(Context->engine, 1, &dstRect, 0xCC, 0xCC, dstFormat)); } } if (gcmIS_ERROR(status)) { break; } if (Context->needAlphaDest) { gcsRECT tempRect; tempRect.left = gcmMAX(0, DestRect->l); tempRect.top = gcmMAX(0, DestRect->t); tempRect.right = gcmMIN((int32_t) Dest->w, DestRect->r); tempRect.bottom = gcmMIN((int32_t) Dest->h, DestRect->b); /* Blit back to actual dest. */ gcmERR_BREAK( _MonoBlit(Context, Context->alphaDest.physical, Context->alphaDest.stride, Context->alphaDest.format, diPhysical, diStride, diFormat, &tempRect)); } /* Flush and commit. */ gcmERR_BREAK( gco2D_Flush(Context->engine)); gcmERR_BREAK( gcoHAL_Commit(gcvNULL, gcvFALSE)); } while (gcvFALSE); return status; }
/******************************************************************************* ** ** gcoDUMP_Control ** ** Control dumping. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** gctSTRING FileName ** If 'FileName' is not gcvNULL, it points to the filename to be used for ** capturing all data. If 'FileName' is gcvNULL, turn off any current ** capturing. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_Control( IN gcoDUMP Dump, IN gctSTRING FileName ) { gceSTATUS status = gcvSTATUS_OK; gcsDUMP_FILE header; gctUINT32 pos; gcmHEADER_ARG("Dump=0x%x FileName=0x%x", Dump, FileName); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); do { if (FileName != gcvNULL) { /* Need to create a new dump file. */ if (Dump->file == gcvNULL) { /* Create the dump file. */ gcmERR_BREAK(gcoOS_Open(gcvNULL, FileName, gcvFILE_CREATE, &Dump->file)); /* Write the file header. */ header.signature = gcvDUMP_FILE_SIGNATURE; header.length = Dump->length = 0; header.frames = Dump->frameCount = 0; gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Frame is not yet started. */ Dump->frameStart = 0; } } else { /* Need to close any current dump file. */ if (Dump->file != gcvNULL) { /* Close any open frame. */ if (Dump->frameStart != 0) { gcoDUMP_FrameEnd(Dump); gcoDUMP_FrameBegin(Dump); } /* Get the current position. */ gcmERR_BREAK(gcoOS_GetPos(gcvNULL, Dump->file, &pos)); /* Seek to the beginnnig of the file. */ gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, 0)); /* Make sure we have the correct size. */ gcmASSERT(pos == Dump->length + sizeof(header)); /* Update the file header. */ header.signature = gcvDUMP_FILE_SIGNATURE; header.length = Dump->length; header.frames = Dump->frameCount; gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Seek to the end of the file. */ gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, pos)); /* Close the file. */ gcmERR_BREAK(gcoOS_Close(gcvNULL, Dump->file)); /* Mark the file as closed. */ Dump->file = gcvNULL; } } } while (gcvFALSE); /* Return the status. */ gcmFOOTER(); return status; }
gceSTATUS glfCreateNamedObject( IN glsCONTEXT_PTR Context, IN glsNAMEDOBJECTLIST_PTR List, IN gctUINT32 Name, IN glfNAMEDOBJECTDESTRUCTOR ObjectDestructor, OUT glsNAMEDOBJECT_PTR * ObjectWrapper ) { gceSTATUS status = gcvSTATUS_OK; gcmHEADER_ARG("Context=0x%x List=0x%x Name=%u ObjectDestructor=0x%x ObjectWrapper=0x%x", Context, List, Name, ObjectDestructor, ObjectWrapper); do { glsNAMEDOBJECT_PTR wrapper; glsNAMEDOBJECT_PTR* entry; gctUINT32 index; /* Are there available wrappers in the free list? */ wrapper = List->freeList; if ((Name == 0) && (wrapper != gcvNULL)) { /* Remove the first wrapper from the list. */ List->freeList = wrapper->next; } /* Create a new wrapper. */ else { /* Create a new wrapper. */ wrapper = gcvNULL; /* Generate a name if not specified. */ if (Name == 0) { if (List->nextName == 0) { /* No more names. */ status = gcvSTATUS_OUT_OF_RESOURCES; break; } Name = List->nextName++; } else if (Name > List->nextName) { /* Name for the object has been explicitly specified by the application and it is greater then the next automatic would-be name. Update the next name with the value from the application; this creates a hole in the name range. */ List->nextName = Name + 1; } else if (List->freeList != gcvNULL) { /* Name for the object has been explicitly specified by the application and it is less then or equal to the next automatic would-be name. This means the name most likely lives inside the free list. */ if (List->freeList->name == Name) { wrapper = List->freeList; List->freeList = wrapper->next; } else { glsNAMEDOBJECT_PTR previous = List->freeList; for (wrapper = List->freeList; wrapper != gcvNULL; wrapper = wrapper->next) { if (wrapper->name == Name) { previous->next = wrapper->next; break; } previous = wrapper; } } } if (wrapper == gcvNULL) { /* Allocate wrapper and the user object. */ gcmERR_BREAK(gcoOS_Allocate( gcvNULL, gcmALIGN(sizeof(glsNAMEDOBJECT), 4) + List->objectSize, (gctPOINTER) &wrapper )); /* Set the objects's name. */ wrapper->name = Name; /* Set the object pointer. */ wrapper->object = ((gctUINT8_PTR) wrapper) + gcmALIGN(sizeof(glsNAMEDOBJECT), 4); wrapper->referenceCount = 0; wrapper->listBelonged = List; } } /* Set the destructor. */ wrapper->deleteObject = ObjectDestructor; /* Determine the hash table index. */ index = wrapper->name % glvNAMEDOBJECT_HASHTABLE_SIZE; /* Shortcut to the table entry. */ entry = &List->hashTable[index]; /* Insert into the chain. */ wrapper->next = *entry; *entry = wrapper; glfReferenceNamedObject(wrapper); /* Set the result. */ *ObjectWrapper = wrapper; } while (gcvFALSE); gcmFOOTER(); return status; }
gceSTATUS _FitSurface( IN gcsCOPYBIT_CONTEXT * Context, IN gcsSURFACE * Surface, IN gctUINT32 Width, IN gctUINT32 Height ) { gceSTATUS status = gcvSTATUS_OK; if (Surface == gcvNULL) { return gcvSTATUS_INVALID_ARGUMENT; } do { /* Create the tmp Surfaceace if necessary. */ if ((Surface->surface == gcvNULL) || (Surface->width < Width) || (Surface->height < Height) ) { /* Destroy last surface. */ if (Surface->surface != gcvNULL) { if (Surface->logical != gcvNULL) { gcmERR_BREAK( gcoSURF_Unlock(Surface->surface, Surface->logical)); } gcmERR_BREAK( gcoSURF_Destroy(Surface->surface)); } /* New surface values. */ Surface->format = gcvSURF_A8R8G8B8; Surface->width = Width; Surface->height = Height; gcmERR_BREAK( gcoSURF_Construct(gcvNULL, Surface->width, Surface->height, 1, gcvSURF_BITMAP, Surface->format, gcvPOOL_DEFAULT, &Surface->surface)); gcmERR_BREAK( gcoSURF_Lock(Surface->surface, &Surface->physical, &Surface->logical)); gcmERR_BREAK( gcoSURF_GetAlignedSize(Surface->surface, &Surface->alignedWidth, &Surface->alignedHeight, &Surface->stride)); } } while (gcvFALSE); return status; }