/*******************************************************************************
**
**  gckKERNEL_Dispatch
**
**  Dispatch a command received from the user HAL layer.
**
**  INPUT:
**
**      gckKERNEL Kernel
**          Pointer to an gckKERNEL object.
**
**      gcsHAL_INTERFACE * Interface
**          Pointer to a gcsHAL_INTERFACE structure that defines the command to
**          be dispatched.
**
**  OUTPUT:
**
**      gcsHAL_INTERFACE * Interface
**          Pointer to a gcsHAL_INTERFACE structure that receives any data to be
**          returned.
*/
gceSTATUS gckVGKERNEL_Dispatch(
    IN gckKERNEL Kernel,
    IN gctBOOL FromUser,
    IN OUT gcsHAL_INTERFACE * Interface
    )
{
    gceSTATUS status;
    gcsHAL_INTERFACE * kernelInterface = Interface;
    gcuVIDMEM_NODE_PTR node;
    gctUINT32 processID;

    gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel, Interface);

    /* Verify the arguments. */
    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
    gcmkVERIFY_ARGUMENT(Interface != gcvNULL);

    gcmkONERROR(gckOS_GetProcessID(&processID));

    /* Dispatch on command. */
    switch (Interface->command)
    {
    case gcvHAL_QUERY_VIDEO_MEMORY:
        /* Query video memory size. */
        gcmkERR_BREAK(gckKERNEL_QueryVideoMemory(
            Kernel, kernelInterface
            ));
        break;

    case gcvHAL_QUERY_CHIP_IDENTITY:
        /* Query chip identity. */
        gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity(
            Kernel->vg->hardware,
            &kernelInterface->u.QueryChipIdentity.chipModel,
            &kernelInterface->u.QueryChipIdentity.chipRevision,
            &kernelInterface->u.QueryChipIdentity.chipFeatures,
            &kernelInterface->u.QueryChipIdentity.chipMinorFeatures,
            &kernelInterface->u.QueryChipIdentity.chipMinorFeatures2
            ));
        break;

    case gcvHAL_QUERY_COMMAND_BUFFER:
        /* Query command buffer information. */
        gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer(
            Kernel,
            &kernelInterface->u.QueryCommandBuffer.information
            ));
        break;
    case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
        /* Allocate non-paged memory. */
        gcmkERR_BREAK(gckOS_AllocateContiguous(
            Kernel->os,
            gcvTRUE,
            &kernelInterface->u.AllocateNonPagedMemory.bytes,
            &kernelInterface->u.AllocateNonPagedMemory.physical,
            &kernelInterface->u.AllocateNonPagedMemory.logical
            ));
        break;

    case gcvHAL_FREE_NON_PAGED_MEMORY:
        /* Unmap user logical out of physical memory first. */
        gcmkERR_BREAK(gckOS_UnmapUserLogical(
            Kernel->os,
            kernelInterface->u.AllocateNonPagedMemory.physical,
            kernelInterface->u.AllocateNonPagedMemory.bytes,
            kernelInterface->u.AllocateNonPagedMemory.logical
            ));

        /* Free non-paged memory. */
        gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
            Kernel->os,
            kernelInterface->u.AllocateNonPagedMemory.bytes,
            kernelInterface->u.AllocateNonPagedMemory.physical,
            kernelInterface->u.AllocateNonPagedMemory.logical
            ));
        break;

    case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
        /* Allocate contiguous memory. */
        gcmkERR_BREAK(gckOS_AllocateContiguous(
            Kernel->os,
            gcvTRUE,
            &kernelInterface->u.AllocateNonPagedMemory.bytes,
            &kernelInterface->u.AllocateNonPagedMemory.physical,
            &kernelInterface->u.AllocateNonPagedMemory.logical
            ));
        break;

    case gcvHAL_FREE_CONTIGUOUS_MEMORY:
        /* Unmap user logical out of physical memory first. */
        gcmkERR_BREAK(gckOS_UnmapUserLogical(
            Kernel->os,
            kernelInterface->u.AllocateNonPagedMemory.physical,
            kernelInterface->u.AllocateNonPagedMemory.bytes,
            kernelInterface->u.AllocateNonPagedMemory.logical
            ));

        /* Free contiguous memory. */
        gcmkERR_BREAK(gckOS_FreeContiguous(
            Kernel->os,
            kernelInterface->u.AllocateNonPagedMemory.physical,
            kernelInterface->u.AllocateNonPagedMemory.logical,
            kernelInterface->u.AllocateNonPagedMemory.bytes
            ));
        break;

    case gcvHAL_ALLOCATE_VIDEO_MEMORY:
        {
            gctSIZE_T bytes;
            gctUINT32 bitsPerPixel;
            gctUINT32 bits;

            /* Align width and height to tiles. */
            gcmkERR_BREAK(gckVGHARDWARE_AlignToTile(
                Kernel->vg->hardware,
                kernelInterface->u.AllocateVideoMemory.type,
                &kernelInterface->u.AllocateVideoMemory.width,
                &kernelInterface->u.AllocateVideoMemory.height
                ));

            /* Convert format into bytes per pixel and bytes per tile. */
            gcmkERR_BREAK(gckVGHARDWARE_ConvertFormat(
                Kernel->vg->hardware,
                kernelInterface->u.AllocateVideoMemory.format,
                &bitsPerPixel,
                gcvNULL
                ));

            /* Compute number of bits for the allocation. */
            bits
                = kernelInterface->u.AllocateVideoMemory.width
                * kernelInterface->u.AllocateVideoMemory.height
                * kernelInterface->u.AllocateVideoMemory.depth
                * bitsPerPixel;

            /* Compute number of bytes for the allocation. */
            bytes = gcmALIGN(bits, 8) / 8;

            /* Allocate memory. */
            gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
                Kernel,
                &kernelInterface->u.AllocateVideoMemory.pool,
                bytes,
                64,
                kernelInterface->u.AllocateVideoMemory.type,
                &kernelInterface->u.AllocateVideoMemory.node
                ));
        }
        break;

    case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
        /* Allocate memory. */
        gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
            Kernel,
            &kernelInterface->u.AllocateLinearVideoMemory.pool,
            kernelInterface->u.AllocateLinearVideoMemory.bytes,
            kernelInterface->u.AllocateLinearVideoMemory.alignment,
            kernelInterface->u.AllocateLinearVideoMemory.type,
            &kernelInterface->u.AllocateLinearVideoMemory.node
            ));

        gcmkERR_BREAK(gckKERNEL_AddProcessDB(Kernel,
           processID, gcvDB_VIDEO_MEMORY,
           Interface->u.AllocateLinearVideoMemory.node,
           gcvNULL,
           kernelInterface->u.AllocateLinearVideoMemory.bytes
           ));

        break;

    case gcvHAL_FREE_VIDEO_MEMORY:
#ifdef __QNXNTO__
        /* Unmap the video memory */
        node = Interface->u.FreeVideoMemory.node;

        if ((node->VidMem.memory->object.type == gcvOBJ_VIDMEM) &&
            (node->VidMem.logical != gcvNULL))
        {
            gckKERNEL_UnmapVideoMemory(Kernel,
                                       node->VidMem.logical,
                                       processID,
                                       node->VidMem.bytes);
            node->VidMem.logical = gcvNULL;
        }
#endif /* __QNXNTO__ */

        /* Free video memory. */
        gcmkERR_BREAK(gckVIDMEM_Free(
            Interface->u.FreeVideoMemory.node
            ));

        gcmkERR_BREAK(gckKERNEL_RemoveProcessDB(
            Kernel,
            processID, gcvDB_VIDEO_MEMORY,
            Interface->u.FreeVideoMemory.node
            ));

        break;

    case gcvHAL_MAP_MEMORY:
        /* Map memory. */
        gcmkERR_BREAK(gckKERNEL_MapMemory(
            Kernel,
            kernelInterface->u.MapMemory.physical,
            kernelInterface->u.MapMemory.bytes,
            &kernelInterface->u.MapMemory.logical
            ));
        break;

    case gcvHAL_UNMAP_MEMORY:
        /* Unmap memory. */
        gcmkERR_BREAK(gckKERNEL_UnmapMemory(
            Kernel,
            kernelInterface->u.MapMemory.physical,
            kernelInterface->u.MapMemory.bytes,
            kernelInterface->u.MapMemory.logical
            ));
        break;

    case gcvHAL_MAP_USER_MEMORY:
        /* Map user memory to DMA. */
        gcmkERR_BREAK(gckOS_MapUserMemory(
            Kernel->os,
            gcvCORE_VG,
            kernelInterface->u.MapUserMemory.memory,
            kernelInterface->u.MapUserMemory.physical,
            kernelInterface->u.MapUserMemory.size,
            &kernelInterface->u.MapUserMemory.info,
            &kernelInterface->u.MapUserMemory.address
            ));
        break;

    case gcvHAL_UNMAP_USER_MEMORY:
        /* Unmap user memory. */
        gcmkERR_BREAK(gckOS_UnmapUserMemory(
            Kernel->os,
            gcvCORE_VG,
            kernelInterface->u.UnmapUserMemory.memory,
            kernelInterface->u.UnmapUserMemory.size,
            kernelInterface->u.UnmapUserMemory.info,
            kernelInterface->u.UnmapUserMemory.address
            ));
        break;
    case gcvHAL_LOCK_VIDEO_MEMORY:
        /* Lock video memory. */
        gcmkERR_BREAK(
            gckVIDMEM_Lock(Kernel,
                           Interface->u.LockVideoMemory.node,
                           gcvFALSE,
                           &Interface->u.LockVideoMemory.address));

        node = Interface->u.LockVideoMemory.node;
        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
        {
            /* Map video memory address into user space. */
#ifdef __QNXNTO__
        if (node->VidMem.logical == gcvNULL)
        {
            gcmkONERROR(
                gckKERNEL_MapVideoMemory(Kernel,
                                         FromUser,
                                         Interface->u.LockVideoMemory.address,
                                         processID,
                                         node->VidMem.bytes,
                                         &node->VidMem.logical));
        }

        Interface->u.LockVideoMemory.memory = node->VidMem.logical;
#else
            gcmkERR_BREAK(
                gckKERNEL_MapVideoMemoryEx(Kernel,
                                         gcvCORE_VG,
                                         FromUser,
                                         Interface->u.LockVideoMemory.address,
                                         &Interface->u.LockVideoMemory.memory));
#endif
        }
        else
        {
            Interface->u.LockVideoMemory.memory = node->Virtual.logical;

            /* Success. */
            status = gcvSTATUS_OK;
        }

#if gcdSECURE_USER
        /* Return logical address as physical address. */
        Interface->u.LockVideoMemory.address =
            gcmPTR2INT(Interface->u.LockVideoMemory.memory);
#endif
        gcmkERR_BREAK(
            gckKERNEL_AddProcessDB(Kernel,
                                   processID, gcvDB_VIDEO_MEMORY_LOCKED,
                                   Interface->u.LockVideoMemory.node,
                                   gcvNULL,
                                   0));
        break;

    case gcvHAL_UNLOCK_VIDEO_MEMORY:
        /* Unlock video memory. */
        node = Interface->u.UnlockVideoMemory.node;

#if gcdSECURE_USER
        /* Save node information before it disappears. */
        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
        {
            logical = gcvNULL;
            bytes   = 0;
        }
        else
        {
            logical = node->Virtual.logical;
            bytes   = node->Virtual.bytes;
        }
#endif

        /* Unlock video memory. */
        gcmkERR_BREAK(
            gckVIDMEM_Unlock(Kernel,
                             node,
                             Interface->u.UnlockVideoMemory.type,
                             &Interface->u.UnlockVideoMemory.asynchroneous,
                             gcvFALSE));

#if gcdSECURE_USER
        /* Flush the translation cache for virtual surfaces. */
        if (logical != gcvNULL)
        {
            gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel,
                                                          cache,
                                                          logical,
                                                          bytes));
        }
#endif

        if (Interface->u.UnlockVideoMemory.asynchroneous == gcvFALSE)
        {
            /* There isn't a event to unlock this node, remove record now */
            gcmkERR_BREAK(
                    gckKERNEL_RemoveProcessDB(Kernel,
                        processID, gcvDB_VIDEO_MEMORY_LOCKED,
                        Interface->u.UnlockVideoMemory.node));
        }

        break;
    case gcvHAL_USER_SIGNAL:
#if !USE_NEW_LINUX_SIGNAL
        /* Dispatch depends on the user signal subcommands. */
        switch(Interface->u.UserSignal.command)
        {
        case gcvUSER_SIGNAL_CREATE:
            /* Create a signal used in the user space. */
            gcmkERR_BREAK(
                gckOS_CreateUserSignal(Kernel->os,
                                       Interface->u.UserSignal.manualReset,
                                       &Interface->u.UserSignal.id));

            gcmkVERIFY_OK(
                gckKERNEL_AddProcessDB(Kernel,
                                       processID, gcvDB_SIGNAL,
                                       gcmINT2PTR(Interface->u.UserSignal.id),
                                       gcvNULL,
                                       0));
            break;

        case gcvUSER_SIGNAL_DESTROY:
            /* Destroy the signal. */
            gcmkERR_BREAK(
                gckOS_DestroyUserSignal(Kernel->os,
                                        Interface->u.UserSignal.id));

            gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
                Kernel,
                processID, gcvDB_SIGNAL,
                gcmINT2PTR(Interface->u.UserSignal.id)));
            break;

        case gcvUSER_SIGNAL_SIGNAL:
            /* Signal the signal. */
            gcmkERR_BREAK(
                gckOS_SignalUserSignal(Kernel->os,
                                       Interface->u.UserSignal.id,
                                       Interface->u.UserSignal.state));
            break;

        case gcvUSER_SIGNAL_WAIT:
            /* Wait on the signal. */
            status = gckOS_WaitUserSignal(Kernel->os,
                                          Interface->u.UserSignal.id,
                                          Interface->u.UserSignal.wait);
            break;

        default:
            /* Invalid user signal command. */
            gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
        }
#endif
        break;

    case gcvHAL_COMMIT:
        /* Commit a command and context buffer. */
        gcmkERR_BREAK(gckVGCOMMAND_Commit(
            Kernel->vg->command,
            kernelInterface->u.VGCommit.context,
            kernelInterface->u.VGCommit.queue,
            kernelInterface->u.VGCommit.entryCount,
            kernelInterface->u.VGCommit.taskTable
            ));
        break;
    case gcvHAL_VERSION:
        kernelInterface->u.Version.major = gcvVERSION_MAJOR;
        kernelInterface->u.Version.minor = gcvVERSION_MINOR;
        kernelInterface->u.Version.patch = gcvVERSION_PATCH;
        kernelInterface->u.Version.build = gcvVERSION_BUILD;
        status = gcvSTATUS_OK;
        break;

    case gcvHAL_GET_BASE_ADDRESS:
        /* Get base address. */
        gcmkERR_BREAK(
            gckOS_GetBaseAddress(Kernel->os,
                                 &kernelInterface->u.GetBaseAddress.baseAddress));
        break;
    default:
        /* Invalid command. */
        status = gcvSTATUS_INVALID_ARGUMENT;
    }

OnError:
    /* Save status. */
    kernelInterface->status = status;

    gcmkFOOTER();

    /* Return the status. */
    return status;
}
Exemplo n.º 2
0
EGLAPI EGLBoolean EGLAPIENTRY
eglChooseConfig(
    EGLDisplay Dpy,
    const EGLint *attrib_list,
    EGLConfig *configs,
    EGLint config_size,
    EGLint *num_config
    )
{
    VEGLThreadData thread;
    VEGLDisplay dpy;
    struct eglConfig criteria = { 0 };
    EGLint config;

    gcmHEADER_ARG("Dpy=0x%x attrib_list=0x%x configs=0x%x config_size=%d",
                  Dpy, attrib_list, configs, config_size);

    /* Get thread data. */
    thread = veglGetThreadData();
    if (thread == gcvNULL)
    {
        gcmTRACE(
            gcvLEVEL_ERROR,
            "%s(%d): veglGetThreadData failed.",
            __FUNCTION__, __LINE__
            );

        gcmFOOTER_ARG("return=%d", EGL_FALSE);
        return EGL_FALSE;
    }

    /* Create a shortcut to the display. */
    dpy = VEGL_DISPLAY(Dpy);

    /* Test for valid EGLDisplay structure. */
    if ((dpy == gcvNULL)
    ||  (dpy->signature != EGL_DISPLAY_SIGNATURE)
    )
    {
        /* Bad display. */
        thread->error = EGL_BAD_DISPLAY;
        gcmFOOTER_ARG("return=%d", EGL_FALSE);
        return EGL_FALSE;
    }

    if (num_config == gcvNULL)
    {
        /* Bad parameter. */
        thread->error = EGL_BAD_PARAMETER;
        gcmFOOTER_ARG("return=%d", EGL_FALSE);
        return EGL_FALSE;
    }

    /* Parse attributes. */
    if (!veglParseAttributes(dpy, attrib_list, &criteria))
    {
        /* Bail out on invalid or non-matching attributes. */
        gcmFOOTER_ARG("return=%d", EGL_FALSE);
        return EGL_FALSE;
    }

    /* Reference the EGLDisplay. */
    if (!veglReferenceDisplay(thread, dpy))
    {
        /* Not initialized. */
        thread->error = EGL_NOT_INITIALIZED;
        gcmFOOTER_ARG("return=%d", EGL_FALSE);
        return EGL_FALSE;
    }

    /* Reset number of configurations. */
    *num_config = 0;

    /* Walk through all configurations. */
    for (config = 0; config < dpy->configCount; config++)
    {
        /* Get pointer to configuration. */
        VEGLConfig configuration = &dpy->config[config];

        gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                      "%s: examining config index=%d",
                      __FUNCTION__, config);

		if (criteria.configId != EGL_DONT_CARE)
        {
            if (!((criteria.configId == configuration->configId) ||
                ((criteria.configId == 0) && configuration->defaultConfig)))
            {
                /* Criterium doesn't match. */
                gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                    "  rejected on config ID.");
                continue;
            }
            else
            {
                *num_config += 1;

                if (configs != gcvNULL)
                {
                    /* Copy configuration into specified buffer. */
                    *configs = configuration;
                }

                break;
            }
        }

        /* Check configuration against criteria. */
        if (criteria.bufferSize > configuration->bufferSize)
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on buffer size.");
            continue;
        }

        if (criteria.alphaSize > configuration->alphaSize)
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on alpha size.");
            continue;
        }

        if (criteria.blueSize > configuration->blueSize)
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on blue size.");
            continue;
        }

        if (criteria.greenSize > configuration->greenSize)
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on green size.");
            continue;
        }

        if (criteria.redSize > configuration->redSize)
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on red size.");
            continue;
        }

        if (criteria.depthSize > configuration->depthSize)
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on depth size.");
            continue;
        }

        if (criteria.stencilSize > configuration->stencilSize)
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on stencil size.");
            continue;
        }

        if ((criteria.configCaveat != (EGLenum) EGL_DONT_CARE)
        &&  (criteria.configCaveat != configuration->configCaveat)
        )
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on config caveat.");
            continue;
        }

        if ((criteria.configId != EGL_DONT_CARE) &&
            !((criteria.configId == configuration->configId) ||
              ((criteria.configId == 0) && configuration->defaultConfig)))
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on config ID.");
            continue;
        }

        if ((criteria.nativeRenderable != (EGLBoolean) EGL_DONT_CARE)
        &&  criteria.nativeRenderable
        &&  (criteria.nativeRenderable != configuration->nativeRenderable)
        )
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on native renderable.");
            continue;
        }

        if ((criteria.nativeVisualType != EGL_DONT_CARE) &&
            (criteria.nativeVisualType != configuration->nativeVisualType))
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on native visual type.");
            continue;
        }

        if (criteria.samples > configuration->samples)
        {
            if ((criteria.samples == 1) && (configuration->samples == 0))
            {
                /* Criterium still matches. */
            }
            else
            {
                /* Criterium doesn't match. */
                gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                              "  rejected on samples.");
                continue;
            }
        }

        if (criteria.sampleBuffers > configuration->sampleBuffers)
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on sample buffers.");
            continue;
        }

        if ((criteria.surfaceType != (EGLenum) EGL_DONT_CARE)
        &&  !(criteria.surfaceType & configuration->surfaceType)
        )
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on surface type.");
            continue;
        }

        if ((criteria.bindToTetxureRGB != (EGLBoolean) EGL_DONT_CARE)
        &&  (criteria.bindToTetxureRGB != configuration->bindToTetxureRGB)
        )
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on bind to tetxure RGB.");
            continue;
        }

        if ((criteria.bindToTetxureRGBA != (EGLBoolean) EGL_DONT_CARE)
        &&  (criteria.bindToTetxureRGBA != configuration->bindToTetxureRGBA)
        )
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on bind to tetxure RGBA.");
            continue;
        }

        if (criteria.luminanceSize > configuration->luminanceSize)
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on luminance size.");
            continue;
        }

        if (criteria.alphaMaskSize > configuration->alphaMaskSize)
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on alpha mask size.");
            continue;
        }

        if ((criteria.colorBufferType != (EGLenum) EGL_DONT_CARE)
        &&  (criteria.colorBufferType != configuration->colorBufferType)
        )
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on color buffer type.");
            continue;
        }

        if ((criteria.renderableType != (EGLenum) EGL_DONT_CARE)
        &&  ((criteria.renderableType & configuration->renderableType)
             != criteria.renderableType)
        )
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on renderable type.");
            continue;
        }

        if ((criteria.conformant != (EGLenum) EGL_DONT_CARE)
        &&  (criteria.conformant != 0)
        &&  !(criteria.conformant & configuration->conformant)
        )
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on conformant.");
            continue;
        }

        if ((criteria.matchNativePixmap != EGL_DONT_CARE)
        &&  (criteria.matchNativePixmap != EGL_NONE)
        )
        {
            EGLBoolean bMatch = EGL_TRUE;
            gctUINT width, height;
            gceSURF_FORMAT format = gcvSURF_UNKNOWN;
            gctUINT bitsPerPixel;

            if (!(configuration->surfaceType & EGL_PIXMAP_BIT)
            ||  !veglGetPixmapInfo(dpy->hdc,
                                   (NativePixmapType)
                                   gcmINT2PTR(criteria.matchNativePixmap),
                                   &width, &height,
                                   &bitsPerPixel,
                                   &format)
            )
            {
                /* surface type of config is not EGL_PIXMAP_BIT or bad pixmap. */
                gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                              "  rejected on match native pixmap.");
                continue;
            }

            switch (format)
            {
            case gcvSURF_R5G6B5:
                if ((configuration->redSize   != 5)
                ||  (configuration->greenSize != 6)
                ||  (configuration->blueSize  != 5)
                )
                {
                    bMatch = EGL_FALSE;
                }
                break;

            case gcvSURF_X8R8G8B8:
                if ((configuration->redSize   != 8)
                ||  (configuration->greenSize != 8)
                ||  (configuration->blueSize  != 8)
                ||  (configuration->alphaSize != 0)
                )
                {
                    bMatch = EGL_FALSE;
                }
                break;

            default:
                break;
            }

            if (!bMatch)
            {
                /* Criterium doesn't match. */
                gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                              "  rejected on match native pixmap.");
                continue;
            }
        }

        if ((criteria.matchFormat != (EGLenum) EGL_DONT_CARE)
        &&  (criteria.matchFormat != (EGLenum) EGL_NONE)
        )
        {
            EGLBoolean bMatch = EGL_TRUE;

            switch(criteria.matchFormat)
            {
            case EGL_FORMAT_RGB_565_EXACT_KHR:
                if (configuration->matchFormat != EGL_FORMAT_RGB_565_EXACT_KHR)
                {
                    bMatch = EGL_FALSE;
                }
                break;

            case EGL_FORMAT_RGB_565_KHR:
                if ((configuration->matchFormat != EGL_FORMAT_RGB_565_EXACT_KHR)
                &&  (configuration->matchFormat != EGL_FORMAT_RGB_565_KHR)
                )
                {
                    bMatch = EGL_FALSE;
                }
                break;

            case EGL_FORMAT_RGBA_8888_EXACT_KHR:
                if (configuration->matchFormat != EGL_FORMAT_RGBA_8888_EXACT_KHR)
                {
                    bMatch = EGL_FALSE;
                }
                break;

            case EGL_FORMAT_RGBA_8888_KHR:
                if ((configuration->matchFormat != EGL_FORMAT_RGBA_8888_EXACT_KHR)
                &&  (configuration->matchFormat != EGL_FORMAT_RGBA_8888_KHR)
                )
                {
                    bMatch = EGL_FALSE;
                }
                break;

            default:
                break;
            }

            if (!bMatch)
            {
                /* Criterium doesn't match. */
                gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                              "  rejected on conformant.");
                continue;
            }
        }

        if ((criteria.recordableConfig != (EGLBoolean) EGL_DONT_CARE)
        &&  (criteria.recordableConfig != configuration->recordableConfig)
        )
        {
            /* Criterium doesn't match. */
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "  rejected on recordable config.");
            continue;
        }

        gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG, "  accepted.");

        if (configs != gcvNULL)
        {
            /* Copy configuration into specified buffer. */
            configs[*num_config] = configuration;
        }

        *num_config += 1;

        if (*num_config == config_size)
        {
            /* Bail out if the specified buffer is full. */
            break;
        }
    }

    if ((*num_config > 1) && (configs != gcvNULL))
    {
        /* Sort the matching configurations. */
        veglSort((VEGLConfig *) configs, *num_config, &criteria);
    }

    /* Dereference the EGLDisplay. */
    veglDereferenceDisplay(thread, dpy, EGL_FALSE);

    /* Success. */
    thread->error = EGL_SUCCESS;
    gcmDUMP_API("${EGL eglChooseConfig 0x%08X (0x%08X) (0x%08X) 0x%08X "
                "(0x%08X)",
                Dpy, attrib_list, configs, config_size, num_config);
    gcmDUMP_API_ARRAY_TOKEN(attrib_list, EGL_NONE);
    gcmDUMP_API_ARRAY(configs, *num_config);
    gcmDUMP_API_ARRAY(num_config, 1);
    gcmDUMP_API("$}");
    gcmFOOTER_ARG("*num_config=%d", *num_config);
    return EGL_TRUE;
}
gceSTATUS
gckKERNEL_MapLogicalToPhysical(
    IN gckKERNEL Kernel,
    IN gctHANDLE Process,
    IN OUT gctPOINTER * Data
    )
{
    gctUINT i, oldest;
    gceSTATUS status;
    gctUINT32 baseAddress;

    gcmkHEADER_ARG("Kernel=0x%x Process=0x%x *Data=0x%x",
                   Kernel, Process, gcmOPT_POINTER(Data));

    /* Verify the arguments. */
    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
    gcmkVERIFY_ARGUMENT(Data != gcvNULL);

    /* Get base address. */
    gcmkONERROR(gckHARDWARE_GetBaseAddress(Kernel->hardware, &baseAddress));

    /* Walk all used cache slots. */
    for (i = oldest = 0; i < Kernel->cacheSlots; ++i)
    {
        if ((Kernel->cache[i].logical == *Data)
        &&  (Kernel->cache[i].process == Process)
        )
        {
            /* Bail out. */
            break;
        }

        if (i == 0)
        {
            /* First slot. */
            oldest = i;
        }

        /* Test if this cache slot is older. */
        else if (Kernel->cache[i].stamp < Kernel->cache[oldest].stamp)
        {
            oldest = i;
        }
    }

    /* See if we had a match. */
    if (i == Kernel->cacheSlots)
    {
        /* See if there is room in the cache. */
        if (i < gcmCOUNTOF(Kernel->cache))
        {
            /* Just append to the cache. */
            i = Kernel->cacheSlots++;
        }

        else
        {
            /* Evict the oldest cache line. */
            i = oldest;
        }

        /* Initialize the cache line. */
        Kernel->cache[i].logical = *Data;
        Kernel->cache[i].process = Process;

        /* Map the logical address to a DMA address. */
        gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os,
                                             *Data,
                                             &Kernel->cache[i].dma));

        if (baseAddress != 0)
        {
            gctBOOL needBase;

            /* Does this state load need a base address? */
            gcmkONERROR(gckHARDWARE_NeedBaseAddress(Kernel->hardware,
                                                    ((gctUINT32_PTR) Data)[-1],
                                                    &needBase));

            if (needBase)
            {
                /* Add the base address. */
                Kernel->cache[i].dma += baseAddress;
            }
        }
    }

    /* Increment time stamp of the cache slot. */
    Kernel->cache[i].stamp = Kernel->cacheTimeStamp++;

    /* Return DMA address. */
    *Data = gcmINT2PTR(Kernel->cache[i].dma);

    /* Success. */
    gcmkFOOTER_ARG("*Data=0x%08x", *Data);
    return gcvSTATUS_OK;

OnError:
    gcmkLOG_ERROR_STATUS();
    /* Return the status. */
    gcmkFOOTER();
    return status;
}
Exemplo n.º 4
0
static EGLBoolean
veglParseAttributes(
    VEGLDisplay Display,
    const EGLint * AttributeList,
    VEGLConfig Configuration
    )
{
    VEGLThreadData thread;
    EGLenum attribute;
    EGLint value = 0;

    /* Get thread data. */
    thread = veglGetThreadData();
    if (thread == gcvNULL)
    {
        gcmTRACE(
            gcvLEVEL_ERROR,
            "%s(%d): veglGetThreadData failed.",
            __FUNCTION__, __LINE__
            );

        return EGL_FALSE;
    }

    /* Assume success. */
    thread->error = EGL_SUCCESS;

    /* Fill in default attributes. */
    Configuration->bufferSize        = 0;
    Configuration->alphaSize         = 0;
    Configuration->blueSize          = 0;
    Configuration->greenSize         = 0;
    Configuration->redSize           = 0;
    Configuration->depthSize         = 0;
    Configuration->stencilSize       = 0;
    Configuration->configCaveat      = (EGLenum) EGL_DONT_CARE;
    Configuration->configId          = EGL_DONT_CARE;
    Configuration->nativeRenderable  = (EGLBoolean) EGL_DONT_CARE;
    Configuration->nativeVisualType  = EGL_DONT_CARE;
    Configuration->samples           = 0;
    Configuration->sampleBuffers     = 0;
    Configuration->surfaceType       = EGL_WINDOW_BIT;
    Configuration->bindToTetxureRGB  = (EGLBoolean) EGL_DONT_CARE;
    Configuration->bindToTetxureRGBA = (EGLBoolean) EGL_DONT_CARE;
    Configuration->luminanceSize     = 0;
    Configuration->alphaMaskSize     = 0;
    Configuration->colorBufferType   = EGL_RGB_BUFFER;
    Configuration->renderableType    = EGL_OPENGL_ES_BIT;
    Configuration->conformant        = 0;
    Configuration->matchFormat       = (EGLenum) EGL_DONT_CARE;
    Configuration->matchNativePixmap = EGL_NONE;
    Configuration->recordableConfig  = (EGLBoolean) EGL_DONT_CARE;

    /* Parse the attribute list. */
    do
    {
        if (AttributeList != gcvNULL)
        {
            attribute      = AttributeList[0];
            value          = AttributeList[1];
            AttributeList += 2;
        }
        else
        {
            attribute = EGL_NONE;
        }

        switch (attribute)
        {
        case EGL_BUFFER_SIZE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                         "%s: EGL_BUFFER_SIZE=%d",
                         __FUNCTION__, value);
            Configuration->bufferSize = value;
            break;

        case EGL_ALPHA_SIZE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                         "%s: EGL_ALPHA_SIZE=%d",
                         __FUNCTION__, value);
            Configuration->alphaSize = value;
            break;

        case EGL_BLUE_SIZE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_BLUE_SIZE=%d",
                          __FUNCTION__, value);
            Configuration->blueSize = value;
            break;

        case EGL_GREEN_SIZE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_GREEN_SIZE=%d",
                          __FUNCTION__, value);
            Configuration->greenSize = value;
            break;

        case EGL_RED_SIZE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_RED_SIZE=%d",
                          __FUNCTION__, value);
            Configuration->redSize = value;
            break;

        case EGL_DEPTH_SIZE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_DEPTH_SIZE=%d",
                          __FUNCTION__, value);
            Configuration->depthSize = value;
            break;

        case EGL_STENCIL_SIZE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_STENCIL_SIZE=%d",
                          __FUNCTION__, value);
            Configuration->stencilSize = value;
            break;

        case EGL_CONFIG_CAVEAT:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_CONFIG_CAVEAT=%d",
                          __FUNCTION__, value);
            Configuration->configCaveat = value;
            break;

        case EGL_CONFIG_ID:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_CONFIG_ID=%d",
                          __FUNCTION__, value);
            Configuration->configId = value;
            break;

        case EGL_LEVEL:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_LEVEL=%d",
                          __FUNCTION__, value);
            if ((value != EGL_DONT_CARE) && (value != 0))
            {
                return EGL_FALSE;
            }
            break;

        case EGL_MAX_PBUFFER_WIDTH:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_MAX_PBUFFER_WIDTH=%d",
                          __FUNCTION__, value);
            if ((value != EGL_DONT_CARE) && (value > thread->maxWidth))
            {
                return EGL_FALSE;
            }
            break;

        case EGL_MAX_PBUFFER_HEIGHT:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_MAX_PBUFFER_HEIGHT=%d",
                          __FUNCTION__, value);
            if ((value != EGL_DONT_CARE) && (value > thread->maxHeight))
            {
                return EGL_FALSE;
            }
            break;

        case EGL_MAX_PBUFFER_PIXELS:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_MAX_PBUFFER_PIXELS=%d",
                          __FUNCTION__, value);
            if ( (value != EGL_DONT_CARE) &&
                 (value > thread->maxWidth * thread->maxHeight) )
            {
                return EGL_FALSE;
            }
            break;

        case EGL_NATIVE_RENDERABLE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_NATIVE_RENDERABLE=%d",
                          __FUNCTION__, value);
            Configuration->nativeRenderable = value;
            break;

        case EGL_NATIVE_VISUAL_ID:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_NATIVE_VISUAL_ID=%d",
                          __FUNCTION__, value);
            if
            (
                (value != EGL_DONT_CARE)
                &&
                (gcmINT2PTR(value) != (void*) Display->hdc)
            )
            {
                return EGL_FALSE;
            }
            break;

        case EGL_NATIVE_VISUAL_TYPE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_NATIVE_VISUAL_TYPE=%d",
                          __FUNCTION__, value);
            Configuration->nativeVisualType = value;
            break;

        case EGL_SAMPLES:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_SAMPLES=%d",
                          __FUNCTION__, value);
            Configuration->samples = value;
            break;

        case EGL_SAMPLE_BUFFERS:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_SAMPLE_BUFFERS=%d",
                          __FUNCTION__, value);
            Configuration->sampleBuffers = value;
            break;

        case EGL_SURFACE_TYPE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_SURFACE_TYPE=%d",
                          __FUNCTION__, value);
            Configuration->surfaceType = value;
            break;

        case EGL_TRANSPARENT_TYPE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_TRANSPARENT_TYPE=%d",
                          __FUNCTION__, value);
            if ((value != EGL_NONE) && (value != EGL_DONT_CARE))
            {
                return EGL_FALSE;
            }
            break;

        case EGL_TRANSPARENT_BLUE_VALUE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_TRANSPARENT_BLUE_VALUE=%d",
                          __FUNCTION__, value);
            if (value != EGL_DONT_CARE)
            {
                return EGL_FALSE;
            }
            break;

        case EGL_TRANSPARENT_GREEN_VALUE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_TRANSPARENT_GREEN_VALUE=%d",
                          __FUNCTION__, value);
            if (value != EGL_DONT_CARE)
            {
                return EGL_FALSE;
            }
            break;

        case EGL_TRANSPARENT_RED_VALUE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_TRANSPARENT_RED_VALUE=%d",
                          __FUNCTION__, value);
            if (value != EGL_DONT_CARE)
            {
                return EGL_FALSE;
            }
            break;

        case EGL_BIND_TO_TEXTURE_RGB:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_BIND_TO_TEXTURE_RGB=%d",
                          __FUNCTION__, value);
            Configuration->bindToTetxureRGB = value;
            break;

        case EGL_BIND_TO_TEXTURE_RGBA:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_BIND_TO_TEXTURE_RGBA=%d",
                          __FUNCTION__, value);
            Configuration->bindToTetxureRGBA = value;
            break;

        case EGL_MIN_SWAP_INTERVAL:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_MIN_SWAP_INTERVAL=%d",
                          __FUNCTION__, value);
            if ((value != EGL_DONT_CARE) && (value > 1))
            {
                return EGL_FALSE;
            }
            break;

        case EGL_MAX_SWAP_INTERVAL:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_MAX_SWAP_INTERVAL=%d",
                          __FUNCTION__, value);
            if ((value != EGL_DONT_CARE) && (value > 1))
            {
                return EGL_FALSE;
            }
            break;

        case EGL_LUMINANCE_SIZE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_LUMINANCE_SIZE=%d",
                          __FUNCTION__, value);
            Configuration->luminanceSize = value;
            break;

        case EGL_ALPHA_MASK_SIZE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_ALPHA_MASK_SIZE=%d",
                          __FUNCTION__, value);
            Configuration->alphaMaskSize = value;
            break;

        case EGL_COLOR_BUFFER_TYPE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_COLOR_BUFFER_TYPE=%d",
                          __FUNCTION__, value);
            Configuration->colorBufferType = value;
            break;

        case EGL_RENDERABLE_TYPE:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_RENDERABLE_TYPE=%d",
                          __FUNCTION__, value);
            Configuration->renderableType = value;
            break;

        case EGL_CONFORMANT:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_RENDERABLE_TYPE=%d",
                          __FUNCTION__, value);
            Configuration->conformant = value;
            break;

        case EGL_MATCH_FORMAT_KHR:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_MATCH_FORMAT_KHR=%d",
                          __FUNCTION__, value);
            Configuration->matchFormat = value;
            break;

        case EGL_MATCH_NATIVE_PIXMAP:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_MATCH_NATIVE_PIXMAP=%d",
                          __FUNCTION__, value);
            Configuration->matchNativePixmap = value;
            break;

        case EGL_RECORDABLE_ANDROID:
            gcmTRACE_ZONE(gcvLEVEL_INFO, gcdZONE_EGL_CONFIG,
                          "%s: EGL_RECORDABLE_ANDROID=%d",
                          __FUNCTION__, value);
            Configuration->recordableConfig = value;
            break;

        case EGL_NONE:
            break;

        default:
            /* Bad attribute. */
            thread->error = EGL_BAD_ATTRIBUTE;
            return EGL_FALSE;
        }
    }
    while (attribute != EGL_NONE);

    /* Success. */
    return EGL_TRUE;
}