/* \brief render scene */ GLHCKAPI void glhckRender(void) { unsigned int ti, oi, ts, os, tc, oc; char kt; glhckTexture *t; glhckObject *o; __GLHCKobjectQueue *objects; __GLHCKtextureQueue *textures; GLHCK_INITIALIZED(); TRACE(2); /* can't render */ if (!glhckInitialized() || !_glhckRenderInitialized()) return; objects = &GLHCKRD()->objects; textures = &GLHCKRD()->textures; /* store counts for enumeration, +1 for untexture objects */ tc = textures->count+1; oc = objects->count; /* nothing to draw */ if (!oc) return; /* draw in sorted texture order */ for (ti = 0, ts = 0; ti != tc; ++ti) { if (ti < tc-1) { if (!(t = textures->queue[ti])) continue; } else t = NULL; /* untextured object */ for (oi = 0, os = 0, kt = 0; oi != oc; ++oi) { if (!(o = objects->queue[oi])) continue; if (o->material) { /* don't draw if not same texture or opaque, * opaque objects are drawn last */ if (o->material->texture != t || (o->material->blenda != GLHCK_ZERO || o->material->blendb != GLHCK_ZERO)) { if (o->material->texture == t) kt = 1; /* don't remove texture from queue */ if (os != oi) objects->queue[oi] = NULL; objects->queue[os++] = o; continue; } } else if (t) { /* no material, but texture requested */ if (os != oi) objects->queue[oi] = NULL; objects->queue[os++] = o; continue; } /* render object */ glhckObjectRender(o); glhckObjectFree(o); /* referenced on draw call */ objects->queue[oi] = NULL; --objects->count; } /* check if we need texture again or not */ if (kt) { if (ts != ti) textures->queue[ti] = NULL; textures->queue[ts++] = t; } else { if (t) { glhckTextureFree(t); /* ref is increased on draw call! */ textures->queue[ti] = NULL; --textures->count; } } } /* store counts for enumeration, +1 for untextured objects */ tc = textures->count+1; oc = objects->count; /* FIXME: shift queue here */ if (oc) { } /* draw opaque objects next, * FIXME: this should not be done in texture order, * instead draw from farthest to nearest. (I hate opaque objects) */ for (ti = 0; ti != tc && oc; ++ti) { if (ti < tc-1) { if (!(t = textures->queue[ti])) continue; } else t = NULL; /* untextured object */ for (oi = 0, os = 0; oi != oc; ++oi) { if (!(o = objects->queue[oi])) continue; if (o->material) { /* don't draw if not same texture */ if (o->material->texture != t) { if (os != oi) objects->queue[oi] = NULL; objects->queue[os++] = o; continue; } } else if (t) { if (os != oi) objects->queue[oi] = NULL; objects->queue[os++] = o; continue; } /* render object */ glhckObjectRender(o); glhckObjectFree(o); /* referenced on draw call */ objects->queue[oi] = NULL; --objects->count; } /* this texture is done for */ if (t) { glhckTextureFree(t); /* ref is increased on draw call! */ textures->queue[ti] = NULL; --textures->count; } /* no texture, time to break */ if (!t) break; } /* FIXME: shift queue here if leftovers */ /* good we got no leftovers \o/ */ if (objects->count) { /* something was left un-drawn :o? */ for (oi = 0; oi != objects->count; ++oi) glhckObjectFree(objects->queue[oi]); memset(objects->queue, 0, objects->count * sizeof(glhckObject*)); objects->count = 0; } if (textures->count) { /* something was left un-drawn :o? */ DEBUG(GLHCK_DBG_CRAP, "COUNT UNLEFT %u", textures->count); for (ti = 0; ti != textures->count; ++ti) glhckTextureFree(textures->queue[ti]); memset(textures->queue, 0, textures->count * sizeof(glhckTexture*)); textures->count = 0; } }
/* \brief creates virtual display and inits renderer */ GLHCKAPI int glhckDisplayCreate(int width, int height, glhckRenderType renderType) { GLHCK_INITIALIZED(); CALL(0, "%d, %d, %d", width, height, renderType); if (width <= 0 && height <= 0) goto fail; /* close display if created already */ if (GLHCKR()->type == renderType && renderType != GLHCK_RENDER_AUTO) goto success; else glhckDisplayClose(); /* init renderer */ switch (renderType) { case GLHCK_RENDER_AUTO: #ifdef GLHCK_HAS_OPENGL _glhckRenderOpenGL(); if (_glhckRenderInitialized()) break; #endif #ifdef GLHCK_HAS_OPENGL_FIXED_PIPELINE _glhckRenderOpenGLFixedPipeline(); if (_glhckRenderInitialized()) break; #endif _glhckRenderStub(); break; case GLHCK_RENDER_OPENGL: case GLHCK_RENDER_GLES2: #ifdef GLHCK_HAS_OPENGL _glhckRenderOpenGL(); #else DEBUG(GLHCK_DBG_ERROR, "OpenGL support was not compiled in!"); #endif break; case GLHCK_RENDER_OPENGL_FIXED_PIPELINE: case GLHCK_RENDER_GLES1: #ifdef GLHCK_HAS_OPENGL_FIXED_PIPELINE _glhckRenderOpenGLFixedPipeline(); #else DEBUG(GLHCK_DBG_ERROR, "OpenGL Fixed Pipeline support was not compiled in!"); #endif break; case GLHCK_RENDER_STUB: default: _glhckRenderStub(); break; } /* check that initialization was success */ if (!_glhckRenderInitialized()) goto fail; /* check render api and output warnings, * if any function is missing */ _glhckRenderCheckApi(); GLHCKR()->type = renderType; /* default render pass bits */ glhckRenderPass(glhckRenderPassDefaults()); /* default cull face */ glhckRenderCullFace(GLHCK_BACK); /* counter-clockwise are front face by default */ glhckRenderFrontFace(GLHCK_CCW); /* resize display */ glhckDisplayResize(width, height); success: RET(0, "%d", RETURN_OK); return RETURN_OK; fail: RET(0, "%d", RETURN_FAIL); return RETURN_FAIL; }
/* \brief get current flipping */ GLHCKAPI int glhckRenderGetFlip(void) { GLHCK_INITIALIZED(); TRACE(2); return GLHCKRD()->view.flippedProjection; }
/* \brief set vertically flipped rendering mode */ GLHCKAPI void glhckRenderFlip(int flip) { GLHCK_INITIALIZED(); CALL(2, "%d", flip); GLHCKRD()->view.flippedProjection = flip; }
/* \brief set render pass cull face side */ GLHCKAPI void glhckRenderCullFace(glhckCullFaceType face) { GLHCK_INITIALIZED(); CALL(2, "%d", face); GLHCKRP()->cullFace = face; }
/* \brief set render pass front face orientation */ GLHCKAPI void glhckRenderFrontFace(glhckFaceOrientation orientation) { GLHCK_INITIALIZED(); CALL(2, "%d", orientation); GLHCKRP()->frontFace = orientation; }
/* \brief set render pass flags */ GLHCKAPI void glhckRenderPass(unsigned int flags) { GLHCK_INITIALIZED(); CALL(2, "%u", flags); GLHCKRP()->flags = flags; }