Added GLES 1.x spinning cube-rendering code to eglbringuptest
The coordinate, color and index data are uploaded to server-side
buffers by the CGLES1Cube::KhrSetup function. CGLES1Cube::KhrPaint
just sets the view matrix and issues a draw command.
Which demo to display can be selected by passing its name on the
command line, e.g.
eglbringuptest vgline
eglbringuptest gles1cube
If no name is provided, the application defaults to vgline.
/*
* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: RenderQueue implementation
*
*/
/*!
* \internal
* \file
* \brief RenderQueue implementation.
*
* Render queue holds
* meshes and sprites that are added to queue in rendering
* setup. After setup, queue is committed and contents are
* rendered. Queue grows dynamically, its initial size is
* defined in m3g_defs.h.
*/
#ifndef M3G_CORE_INCLUDE
# error included by m3g_core.c; do not compile separately.
#endif
#include "m3g_array.h"
/*----------------------------------------------------------------------
* Private data structures
*--------------------------------------------------------------------*/
/*!
* \internal
* \brief RenderQueue entry object
*/
struct RenderItemImpl
{
Node *node;
Matrix toCamera;
M3Gint subMeshIndex;
M3Guint sortKey;
};
/*!
* \internal
* \brief Drawable queue
*/
struct RenderBucketImpl
{
PointerArray items;
};
/* Sanity checking... */
M3G_CT_ASSERT(M3G_RENDERQUEUE_BUCKET_BITS >= M3G_APPEARANCE_HARD_SORT_BITS);
/*----------------------------------------------------------------------
* Private functions
*--------------------------------------------------------------------*/
static M3G_INLINE RenderBucket *m3gGetRenderBucket(RenderQueue *rq,
M3Guint sortKey,
Interface *m3g)
{
int i = (int)(sortKey >> (32 - M3G_RENDERQUEUE_BUCKET_BITS));
RenderBucket *bucket = rq->buckets[i];
if (!bucket) {
bucket = m3gAllocZ(m3g, sizeof(RenderBucket));
/* array already initialized by zero-allocation; see m3g_array.h */
rq->buckets[i] = bucket;
}
if (i < rq->minBucket) {
rq->minBucket = i;
}
if (i > rq->maxBucket) {
rq->maxBucket = i;
}
return bucket;
}
static void m3gDestroyRenderBucket(RenderBucket *bucket, Interface *m3g)
{
if (bucket) {
int i;
PointerArray *items = &bucket->items;
for (i = 0; i < m3gArraySize(items); ++i) {
m3gFree(m3g, m3gGetArrayElement(items, i));
}
m3gDestroyArray(items, m3g);
}
m3gFree(m3g, bucket);
}
static RenderItem *m3gGetRenderItem(RenderQueue *rq, Interface *m3g)
{
RenderItem *item = rq->freeItems;
if (!item) {
m3gIncStat(m3g, M3G_STAT_RENDERQUEUE_SIZE, 1);
item = m3gAlloc(m3g, sizeof(RenderItem));
}
else {
M3G_VALIDATE_MEMBLOCK(item);
rq->freeItems = *(RenderItem**)item; /* move to next */
}
return item;
}
static void m3gRecycleRenderItem(RenderQueue *rq, RenderItem *item)
{
if (item) {
*(RenderItem**)item = rq->freeItems; /* store "next" pointer */
rq->freeItems = item;
}
}
static M3Gbool m3gInsertRenderItem(RenderBucket *bucket,
RenderItem *item,
Interface *m3g)
{
PointerArray *items = &bucket->items;
int idx = m3gArraySize(items);
/* Do a binary search for the sorting key of the item */
{
M3Guint key = item->sortKey;
int low = 0;
int high = idx;
const RenderItem *cmp;
idx >>= 1;
while (low < high) {
cmp = (const RenderItem*) m3gGetArrayElement(items, idx);
if (cmp->sortKey < key) {
low = idx + 1;
}
else if (cmp->sortKey > key) {
high = idx;
}
else {
break;
}
idx = (low + high) >> 1;
}
}
/* Now that we know where to insert, insert; out of memory here
* returns < 0 */
return (m3gArrayInsert(items, idx, item, m3g) >= 0);
}
/*----------------------------------------------------------------------
* Internal functions
*--------------------------------------------------------------------*/
/*!
* \internal
* \brief Creates a new render queue.
*
* \param m3g M3G interface object
* \return RenderQueue object
*/
static RenderQueue *m3gCreateRenderQueue(Interface *m3g)
{
RenderQueue *rq;
rq = m3gAllocZ(m3g, (M3Gsizei) sizeof(RenderQueue));
return rq;
}
/*!
* \internal
* \brief Destroys a render queue and frees
* all allocated memory.
*
* \param m3g M3G interface object
* \param rq RenderQueue
*/
static void m3gDestroyRenderQueue(Interface *m3g, RenderQueue *rq)
{
if (rq) {
int i;
for (i = 0; i < (1 << M3G_RENDERQUEUE_BUCKET_BITS); ++i) {
RenderBucket *bucket = rq->buckets[i];
m3gDestroyRenderBucket(bucket, m3g);
}
while (rq->freeItems) {
RenderItem *item = rq->freeItems;
rq->freeItems = *(RenderItem**)item;
m3gFree(m3g, item);
}
}
m3gFree(m3g, rq);
}
/*!
* \internal
* \brief Inserts a mesh to the queue. May allocate
* memory if queue size is exceeded.
*
* \param m3g M3G interface object
* \param rq RenderQueue
* \param mesh Mesh object
* \param subMeshIndex submesh index inside mesh
* \param sortKey sorting key
*/
static M3Gbool m3gInsertDrawable(Interface *m3g,
RenderQueue *rq,
Node *node,
const Matrix *toCamera,
M3Gint subMeshIndex,
M3Guint sortKey)
{
RenderItem *item;
RenderBucket *bucket;
item = m3gGetRenderItem(rq, m3g);
if (!item) {
goto OutOfMemory;
}
bucket = m3gGetRenderBucket(rq, sortKey, m3g);
if (!bucket) {
goto OutOfMemory;
}
item->node = node;
item->toCamera = *toCamera;
item->subMeshIndex = subMeshIndex;
item->sortKey = (sortKey << M3G_RENDERQUEUE_BUCKET_BITS);
M3G_BEGIN_PROFILE(m3g, M3G_PROFILE_SETUP_SORT);
if (!m3gInsertRenderItem(bucket, item, m3g)) {
goto OutOfMemory;
}
M3G_END_PROFILE(m3g, M3G_PROFILE_SETUP_SORT);
return M3G_TRUE;
OutOfMemory:
m3gRecycleRenderItem(rq, item);
return M3G_FALSE;
}
/*!
* \internal
* \brief Clears the queue.
*
* \param rq RenderQueue
*/
static void m3gClearRenderQueue(RenderQueue *rq)
{
rq->root = NULL;
rq->lightManager = NULL;
rq->minBucket = (1 << M3G_RENDERQUEUE_BUCKET_BITS);
rq->maxBucket = 0;
}
/*!
* \internal
* \brief Commits the queue by rendering its contents.
*
* \param rq RenderQueue
* \param ctx RenderContext object
*/
static void m3gCommit(RenderQueue *rq, RenderContext *ctx)
{
M3Gint b;
for (b = rq->minBucket; b <= rq->maxBucket; ++b) {
if (rq->buckets[b]) {
PointerArray *items = &rq->buckets[b]->items;
int n = m3gArraySize(items);
int i;
for (i = 0; i < n; ++i) {
RenderItem *item = (RenderItem*) m3gGetArrayElement(items, i);
M3G_VFUNC(Node, item->node, doRender)(
item->node, ctx, &item->toCamera, item->subMeshIndex);
m3gRecycleRenderItem(rq, item);
}
m3gClearArray(items);
m3gIncStat(M3G_INTERFACE(ctx), M3G_STAT_RENDER_NODES_DRAWN, n);
}
}
}