/******************************************************************************* ** ** gckHEAP_Allocate ** ** Allocate data from the heap. ** ** INPUT: ** ** gckHEAP Heap ** Pointer to a gckHEAP object. ** ** IN gctSIZE_T Bytes ** Number of byte to allocate. ** ** OUTPUT: ** ** gctPOINTER * Memory ** Pointer to a variable that will hold the address of the allocated ** memory. */ gceSTATUS gckHEAP_Allocate( IN gckHEAP Heap, IN gctSIZE_T Bytes, OUT gctPOINTER * Memory ) { gctBOOL acquired = gcvFALSE; gcskHEAP_PTR heap; gceSTATUS status; gctSIZE_T bytes; gcskNODE_PTR node, used, prevFree = gcvNULL; gctPOINTER memory = gcvNULL; gcmkHEADER_ARG("Heap=0x%x Bytes=%lu", Heap, Bytes); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP); gcmkVERIFY_ARGUMENT(Bytes > 0); gcmkVERIFY_ARGUMENT(Memory != gcvNULL); /* Determine number of bytes required for a node. */ bytes = gcmALIGN(Bytes + gcmSIZEOF(gcskNODE), 8); /* Acquire the mutex. */ gcmkONERROR( gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE)); acquired = gcvTRUE; /* Check if this allocation is bigger than the default allocation size. */ if (bytes > Heap->allocationSize - gcmSIZEOF(gcskHEAP) - gcmSIZEOF(gcskNODE)) { /* Adjust allocation size. */ Heap->allocationSize = bytes * 2; } else if (Heap->heap != gcvNULL) { gctINT i; /* 2 retries, since we might need to compact. */ for (i = 0; i < 2; ++i) { /* Walk all the heaps. */ for (heap = Heap->heap; heap != gcvNULL; heap = heap->next) { /* Check if this heap has enough bytes to hold the request. */ if (bytes <= heap->size - gcmSIZEOF(gcskNODE)) { prevFree = gcvNULL; /* Walk the chain of free nodes. */ for (node = heap->freeList; node != gcvNULL; node = node->next ) { gcmkASSERT(node->next != gcdIN_USE); /* Check if this free node has enough bytes. */ if (node->bytes >= bytes) { /* Use the node. */ goto UseNode; } /* Save current free node for linked list management. */ prevFree = node; } } } if (i == 0) { /* Compact the heap. */ gcmkVERIFY_OK(_CompactKernelHeap(Heap)); #if gcmIS_DEBUG(gcdDEBUG_CODE) gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP, "===== KERNEL HEAP ====="); gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP, "Number of allocations : %12u", Heap->allocCount); gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP, "Number of bytes allocated : %12llu", Heap->allocBytes); gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP, "Maximum allocation size : %12llu", Heap->allocBytesMax); gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP, "Total number of bytes allocated : %12llu", Heap->allocBytesTotal); gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP, "Number of heaps : %12u", Heap->heapCount); gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP, "Heap memory in bytes : %12llu", Heap->heapMemory); gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP, "Maximum number of heaps : %12u", Heap->heapCountMax); gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP, "Maximum heap memory in bytes : %12llu", Heap->heapMemoryMax); #endif } } } /* Release the mutex. */ gcmkONERROR( gckOS_ReleaseMutex(Heap->os, Heap->mutex)); acquired = gcvFALSE; /* Allocate a new heap. */ gcmkONERROR( gckOS_AllocateMemory(Heap->os, Heap->allocationSize, &memory)); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP, "Allocated heap 0x%x (%lu bytes)", memory, Heap->allocationSize); /* Acquire the mutex. */ gcmkONERROR( gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE)); acquired = gcvTRUE; /* Use the allocated memory as the heap. */ heap = (gcskHEAP_PTR) memory; /* Insert this heap to the head of the chain. */ heap->next = Heap->heap; heap->prev = gcvNULL; heap->size = Heap->allocationSize - gcmSIZEOF(gcskHEAP); if (heap->next != gcvNULL) { heap->next->prev = heap; } Heap->heap = heap; /* Mark the end of the heap. */ node = (gcskNODE_PTR) ( (gctUINT8_PTR) heap + Heap->allocationSize - gcmSIZEOF(gcskNODE) ); node->bytes = 0; node->next = gcvNULL; /* Create a free list. */ node = (gcskNODE_PTR) (heap + 1); heap->freeList = node; /* Initialize the free list. */ node->bytes = heap->size - gcmSIZEOF(gcskNODE); node->next = gcvNULL; /* No previous free. */ prevFree = gcvNULL; #if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE) /* Update profiling. */ Heap->heapCount += 1; Heap->heapMemory += Heap->allocationSize; if (Heap->heapCount > Heap->heapCountMax) { Heap->heapCountMax = Heap->heapCount; } if (Heap->heapMemory > Heap->heapMemoryMax) { Heap->heapMemoryMax = Heap->heapMemory; } #endif UseNode: /* Verify some stuff. */ gcmkASSERT(heap != gcvNULL); gcmkASSERT(node != gcvNULL); gcmkASSERT(node->bytes >= bytes); if (heap->prev != gcvNULL) { /* Unlink the heap from the linked list. */ heap->prev->next = heap->next; if (heap->next != gcvNULL) { heap->next->prev = heap->prev; } /* Move the heap to the front of the list. */ heap->next = Heap->heap; heap->prev = gcvNULL; Heap->heap = heap; heap->next->prev = heap; } /* Check if there is enough free space left after usage for another free ** node. */ if (node->bytes - bytes >= gcmSIZEOF(gcskNODE)) { /* Allocated used space from the back of the free list. */ used = (gcskNODE_PTR) ((gctUINT8_PTR) node + node->bytes - bytes); /* Adjust the number of free bytes. */ node->bytes -= bytes; gcmkASSERT(node->bytes >= gcmSIZEOF(gcskNODE)); } else { /* Remove this free list from the chain. */ if (prevFree == gcvNULL) { heap->freeList = node->next; } else { prevFree->next = node->next; } /* Consume the entire free node. */ used = (gcskNODE_PTR) node; bytes = node->bytes; } /* Mark node as used. */ used->bytes = bytes; used->next = gcdIN_USE; #if gcmIS_DEBUG(gcdDEBUG_CODE) used->timeStamp = ++Heap->timeStamp; #endif #if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE) /* Update profile counters. */ Heap->allocCount += 1; Heap->allocBytes += bytes; Heap->allocBytesMax = gcmMAX(Heap->allocBytes, Heap->allocBytesMax); Heap->allocBytesTotal += bytes; #endif /* Release the mutex. */ gcmkVERIFY_OK( gckOS_ReleaseMutex(Heap->os, Heap->mutex)); /* Return pointer to memory. */ *Memory = used + 1; /* Success. */ gcmkFOOTER_ARG("*Memory=0x%x", *Memory); return gcvSTATUS_OK; OnError: if (acquired) { /* Release the mutex. */ gcmkVERIFY_OK( gckOS_ReleaseMutex(Heap->os, Heap->mutex)); } if (memory != gcvNULL) { /* Free the heap memory. */ gckOS_FreeMemory(Heap->os, memory); } /* Return the status. */ gcmkFOOTER(); return status; }
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; }
static void _Policy( IN gckDVFS Dvfs, IN gctUINT32 Load, OUT gctUINT8 *Scale ) { gctUINT8 load[4], nextLoad; gctUINT8 scale; /* Last 4 history. */ load[0] = (Load & 0xFF); load[1] = (Load & 0xFF00) >> 8; load[2] = (Load & 0xFF0000) >> 16; load[3] = (Load & 0xFF000000) >> 24; /* Determine target scale. */ if (load[0] > 54) { _IncreaseScale(Dvfs, Load, &scale); } else { nextLoad = (load[0] + load[1] + load[2] + load[3])/4; scale = Dvfs->currentScale * (nextLoad) / 54; scale = gcmMAX(1, scale); scale = gcmMIN(64, scale); } Dvfs->totalConfig++; Dvfs->loads[(load[0]-1)/8]++; *Scale = scale; if (Dvfs->totalConfig % 100 == 0) { gcmkPRINT("======================================================="); gcmkPRINT("GPU Load: %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d", 8, 16, 24, 32, 40, 48, 56, 64); gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d", _GetLoadHistory(Dvfs,2, 0), _GetLoadHistory(Dvfs,2, 1), _GetLoadHistory(Dvfs,2, 2), _GetLoadHistory(Dvfs,2, 3), _GetLoadHistory(Dvfs,2, 4), _GetLoadHistory(Dvfs,2, 5), _GetLoadHistory(Dvfs,2, 6), _GetLoadHistory(Dvfs,2, 7) ); gcmkPRINT("Frequency(MHz) %-8d %-8d %-8d %-8d %-8d", 58, 120, 240, 360, 480); gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d", _GetFrequencyHistory(Dvfs, 58), _GetFrequencyHistory(Dvfs,120), _GetFrequencyHistory(Dvfs,240), _GetFrequencyHistory(Dvfs,360), _GetFrequencyHistory(Dvfs,480) ); } }
VEGLThreadData veglGetThreadData( void ) { gcsTLS_PTR tls = gcvNULL; gceSTATUS status; #if gcdENABLE_VG gctINT32 i; #endif gcmHEADER(); gcmONERROR(gcoOS_GetTLS(&tls)); if (tls->context == gcvNULL) { gctPOINTER pointer = gcvNULL; VEGLThreadData thread; gcmONERROR(gcoOS_Allocate( gcvNULL, gcmSIZEOF(struct eglThreadData), &pointer )); gcmONERROR(gcoOS_ZeroMemory( pointer, gcmSIZEOF(struct eglThreadData) )); /* Initialize TLS record. */ tls->context = pointer; tls->destructor = _DestroyThreadData; /* Cast the pointer. */ thread = (VEGLThreadData) pointer; /* Initialize the thread data. */ thread->error = EGL_SUCCESS; thread->api = EGL_OPENGL_ES_API; thread->lastClient = 1; thread->worker = gcvNULL; tls->currentType = gcvHARDWARE_3D; #if veglUSE_HAL_DUMP /* Get the gcoDUMP object. */ gcmONERROR(gcoHAL_GetDump(thread->hal, &thread->dump)); #endif #if gcdENABLE_VG gcmONERROR(gcoHAL_QueryChipCount(gcvNULL, &thread->chipCount)); for (i = 0; i < thread->chipCount; i++) { gcmONERROR(gcoHAL_QueryChipLimits(gcvNULL, i, &thread->chipLimits[i])); } for (i = 0; i < thread->chipCount; i++) { thread->maxWidth = gcmMAX(thread->maxWidth, (gctINT32)thread->chipLimits[i].maxWidth); thread->maxHeight = gcmMAX(thread->maxHeight, (gctINT32)thread->chipLimits[i].maxHeight); thread->maxSamples = gcmMAX(thread->maxSamples, (gctINT32)thread->chipLimits[i].maxSamples); } for (i = 0; i < thread->chipCount; i++) { /* Query VAA support. */ if (gcoHAL_QueryChipFeature(gcvNULL, i, gcvFEATURE_VAA)) { thread->vaa = gcvTRUE; break; } } for (i = 0; i < thread->chipCount; i++) { if (gcoHAL_QueryChipFeature(gcvNULL, i, gcvFEATURE_PIPE_VG)) { thread->openVGpipe = _IsHWVGDriverAvailable(thread); break; } } #else /* Query the hardware identity. */ gcmONERROR(gcoHAL_QueryChipIdentity( gcvNULL, &thread->chipModel, gcvNULL, gcvNULL, gcvNULL )); /* Query the hardware capabilities. */ gcmONERROR(gcoHAL_QueryTargetCaps( gcvNULL, (gctUINT32_PTR) &thread->maxWidth, (gctUINT32_PTR) &thread->maxHeight, gcvNULL, (gctUINT32_PTR) &thread->maxSamples )); /* Query VAA support. */ thread->vaa = gcoHAL_IsFeatureAvailable(gcvNULL, gcvFEATURE_VAA) == gcvSTATUS_TRUE; /* Query OpenVG pipe support. */ thread->openVGpipe = gcoHAL_IsFeatureAvailable(gcvNULL, gcvFEATURE_PIPE_VG) == gcvSTATUS_TRUE; #endif gcmTRACE_ZONE( gcvLEVEL_VERBOSE, gcdZONE_EGL_API, "%s(%d): maxWidth=%d maxHeight=%d maxSamples=%d vaa=%d openVG=%d", __FUNCTION__, __LINE__, thread->maxWidth, thread->maxHeight, thread->maxSamples, thread->vaa, thread->openVGpipe ); }