/* \brief unbind texture */ GLHCKAPI void glhckTextureUnbind(glhckTextureTarget target) { CALL(2, "%d", target); if (!GLHCKRD()->texture[GLHCKRD()->activeTexture][target]) return; GLHCKRA()->textureBind(target, 0); GLHCKRD()->texture[GLHCKRD()->activeTexture][target] = NULL; }
/* \brief clear scene */ GLHCKAPI void glhckRenderClear(unsigned int bufferBits) { GLHCK_INITIALIZED(); CALL(2, "%u", bufferBits); if (!_glhckRenderInitialized()) return; GLHCKRA()->clear(bufferBits); }
/* \brief free texture */ GLHCKAPI unsigned int glhckTextureFree(glhckTexture *object) { unsigned int i; if (!glhckInitialized()) return 0; CALL(FREE_CALL_PRIO(object), "%p", object); assert(object); /* there is still references to this object alive */ if (--object->refCounter != 0) goto success; DEBUG(GLHCK_DBG_CRAP, "FREE(%p) %dx%dx%d", object, object->internalWidth, object->internalHeight, object->internalDepth); /* unbind from active slot */ for (i = 0; i != GLHCK_MAX_ACTIVE_TEXTURE; ++i) { if (GLHCKRD()->texture[i][object->target] == object) glhckTextureUnbind(object->target); } /* delete texture if there is one */ if (object->object) GLHCKRA()->textureDelete(1, &object->object); /* free */ IFDO(_glhckFree, object->file); /* remove from world */ _glhckWorldRemove(texture, object, glhckTexture*); /* free */ NULLDO(_glhckFree, object); success: RET(FREE_RET_PRIO(object), "%u", object?object->refCounter:0); return object?object->refCounter:0; }
/* \brief give current program time to glhck */ GLHCKAPI void glhckRenderTime(float time) { GLHCK_INITIALIZED(); CALL(2, "%f", time); if (!_glhckRenderInitialized()) return; GLHCKRA()->time(time); }
/* \brief bind texture */ GLHCKAPI void glhckTextureBind(glhckTexture *object) { CALL(2, "%p", object); assert(object); if (GLHCKRD()->texture[GLHCKRD()->activeTexture][object->target] == object) return; GLHCKRA()->textureBind(object->target, object->object); GLHCKRD()->texture[GLHCKRD()->activeTexture][object->target] = object; }
/* \brief apply texture parameters. */ GLHCKAPI void glhckTextureParameter(glhckTexture *object, const glhckTextureParameters *params) { glhckTexture *old; CALL(2, "%p, %p", object, params); assert(object); /* copy texture parameters over */ memcpy(&object->params, (params?params:glhckTextureDefaultParameters()), sizeof(glhckTextureParameters)); params = &object->params; /* push texture parameters to renderer */ old = glhckTextureCurrentForTarget(object->target); glhckTextureBind(object); GLHCKRA()->textureParameter(object->target, params); if (params->mipmap) GLHCKRA()->textureGenerateMipmap(object->target); if (old) glhckTextureBind(old); }
/* \brief set view matrix */ GLHCKAPI void glhckRenderView(const kmMat4 *mat) { GLHCK_INITIALIZED(); CALL(2, "%p", mat); if (!_glhckRenderInitialized()) return; GLHCKRA()->setView(mat); memcpy(&GLHCKRD()->view.view, mat, sizeof(kmMat4)); }
/* \brief set clear color to render */ GLHCKAPI void glhckRenderClearColor(const glhckColorb *color) { GLHCK_INITIALIZED(); CALL(2, "%p", color); if (!_glhckRenderInitialized()) return; GLHCKRA()->clearColor(color); memcpy(&GLHCKRP()->clearColor, color, sizeof(glhckColorb)); }
/* \brief set renderer's viewport */ GLHCKAPI void glhckRenderViewport(const glhckRect *viewport) { kmMat4 ortho; GLHCK_INITIALIZED(); CALL(1, RECTS, RECT(viewport)); assert(viewport->x >= 0 && viewport->y >= 0 && viewport->w > 0 && viewport->h > 0); if (!_glhckRenderInitialized()) return; /* set viewport on render */ GLHCKRA()->viewport(viewport->x, viewport->y, viewport->w, viewport->h); memcpy(&GLHCKRP()->viewport, viewport, sizeof(glhckRect)); /* update orthographic matrix */ kmMat4OrthographicProjection(&ortho, viewport->x, viewport->w, viewport->h, viewport->y, -1.0f, 1.0f); GLHCKRA()->setOrthographic(&ortho); memcpy(&GLHCKRD()->view.orthographic, &ortho, sizeof(kmMat4)); }
/* \brief active texture index */ GLHCKAPI void glhckTextureActive(unsigned int index) { assert(index < GLHCK_MAX_ACTIVE_TEXTURE && "Tried to active bigger texture index than GLhck supports"); if (GLHCKRD()->activeTexture == index) return; GLHCKRA()->textureActive(index); GLHCKRD()->activeTexture = index; }
/* \brief close the virutal display */ GLHCKAPI void glhckDisplayClose(void) { GLHCK_INITIALIZED(); TRACE(0); if (!_glhckRenderInitialized()) return; memset(&GLHCKR()->features, 0, sizeof(glhckRenderFeatures)); GLHCKRA()->terminate(); GLHCKR()->type = GLHCK_RENDER_AUTO; }
/* \brief clear scene */ GLHCKAPI void glhckRenderClear(unsigned int bufferBits) { GLHCK_INITIALIZED(); CALL(2, "%u", bufferBits); if (!_glhckRenderInitialized()) return; #if EMSCRIPTEN /* when there is no framebuffers bound assume we are in * main loop don't do clear since webgl does clear itself. * XXX: document this behaviour */ int i; for (i = 0; i < GLHCK_FRAMEBUFFER_TYPE_LAST && !GLHCKRD()->framebuffer[i]; ++i); if (i == GLHCK_FRAMEBUFFER_TYPE_LAST) return; #endif GLHCKRA()->clear(bufferBits); }
/* \brief pop render state from stack */ GLHCKAPI void glhckRenderStatePop(void) { __GLHCKrenderState *state, *newState; if (!(state = GLHCKR()->stack)) return; glhckRenderResize(state->width, state->height); memcpy(&GLHCKR()->pass, &state->pass, sizeof(__GLHCKrenderPass)); glhckRenderClearColor(&state->pass.clearColor); glhckRenderViewport(&state->pass.viewport); glhckRenderProjection(&state->view.projection); glhckRenderView(&state->view.view); GLHCKRA()->setOrthographic(&state->view.orthographic); memcpy(&GLHCKRD()->view.orthographic, &state->view.orthographic, sizeof(kmMat4)); glhckRenderFlip(state->view.flippedProjection); newState = (state?state->next:NULL); IFDO(_glhckFree, state); GLHCKR()->stack = newState; }
/* \brief return default texture parameters */ GLHCKAPI const glhckTextureParameters* glhckTextureDefaultParameters(void) { static glhckTextureParameters defaultParameters = { .maxAnisotropy = 16.0f, .minLod = -1000.0f, .maxLod = 1000.0f, .biasLod = 0.0f, .baseLevel = 0, .maxLevel = 1000, .wrapS = GLHCK_REPEAT, .wrapT = GLHCK_REPEAT, .wrapR = GLHCK_REPEAT, .minFilter = GLHCK_NEAREST_MIPMAP_LINEAR, .magFilter = GLHCK_LINEAR, .compareMode = GLHCK_COMPARE_NONE, .compareFunc = GLHCK_LEQUAL, .mipmap = 1, }; return &defaultParameters; } /* \brief return default texture parameters without mipmap and repeat */ GLHCKAPI const glhckTextureParameters* glhckTextureDefaultLinearParameters(void) { static glhckTextureParameters defaultParameters = { .maxAnisotropy = 16.0f, .minLod = -1000.0f, .maxLod = 1000.0f, .biasLod = 0.0f, .baseLevel = 0, .maxLevel = 1000, .wrapS = GLHCK_CLAMP_TO_EDGE, .wrapT = GLHCK_CLAMP_TO_EDGE, .wrapR = GLHCK_CLAMP_TO_EDGE, .minFilter = GLHCK_LINEAR, .magFilter = GLHCK_LINEAR, .compareMode = GLHCK_COMPARE_NONE, .compareFunc = GLHCK_LEQUAL, .mipmap = 0, }; return &defaultParameters; } /* \brief return default sprite parameters */ GLHCKAPI const glhckTextureParameters* glhckTextureDefaultSpriteParameters(void) { static glhckTextureParameters defaultParameters = { .maxAnisotropy = 16.0f, .minLod = -1000.0f, .maxLod = 1000.0f, .biasLod = 0.0f, .baseLevel = 0, .maxLevel = 1000, .wrapS = GLHCK_CLAMP_TO_EDGE, .wrapT = GLHCK_CLAMP_TO_EDGE, .wrapR = GLHCK_CLAMP_TO_EDGE, .minFilter = GLHCK_NEAREST, .magFilter = GLHCK_NEAREST, .compareMode = GLHCK_COMPARE_NONE, .compareFunc = GLHCK_LEQUAL, .mipmap = 0, }; return &defaultParameters; } /* \brief get texture's information */ GLHCKAPI void glhckTextureGetInformation(glhckTexture *object, glhckTextureTarget *target, int *width, int *height, int *depth, int *border, glhckTextureFormat *format, glhckDataType *type) { CALL(0, "%p, %p, %p, %p, %p, %p, %p, %p", object, target, width, height, depth, border, format, type); assert(object); if (target) *target = object->target; if (width) *width = object->width; if (height) *height = object->height; if (depth) *depth = object->depth; if (border) *border = object->border; } /* \brief create texture manually. */ GLHCKAPI int glhckTextureCreate(glhckTexture *object, glhckTextureTarget target, int level, int width, int height, int depth, int border, glhckTextureFormat format, glhckDataType type, int size, const void *data) { glhckTexture *old = NULL; int twidth = width, theight = height, tdepth = depth; CALL(0, "%p, %d, %d, %d, %d, %d, %d, %d, %d, %d, %p", object, target, level, width, height, depth, border, format, type, size, data); assert(object); assert(level >= 0); /* check the true data size, if not provided */ if (!size) size = _glhckSizeForTexture(target, width, height, depth, format, type); /* create texture */ if (!object->object) GLHCKRA()->textureGenerate(1, &object->object); if (!object->object) goto fail; /* set texture type */ object->target = target; /* scale to next pow2 */ _glhckNextPow2(width, height, depth, &twidth, &theight, &tdepth, 0); old = glhckTextureCurrentForTarget(object->target); glhckTextureBind(object); if (width == twidth && height == theight) { GLHCKRA()->textureImage(target, level, twidth, theight, tdepth, border, format, type, size, data); } else { GLHCKRA()->textureImage(target, level, twidth, theight, tdepth, border, format, type, 0, NULL); if (data) { GLHCKRA()->textureFill(target, level, 0, 0, 0, width, height, depth, format, type, size, data); } } if (old) glhckTextureBind(old); /* set rest */ object->target = target; object->width = width; object->height = height; object->depth = depth; object->internalWidth = twidth; object->internalHeight = theight; object->internalDepth = tdepth; object->border = border; object->internalScale.x = (width?(kmScalar)width/twidth:1.0f); object->internalScale.y = (height?(kmScalar)height/theight:1.0f); object->internalScale.z = (depth?(kmScalar)depth/tdepth:1.0f); /* make aprox texture sizes show up in memory graph, even if not allocated */ _glhckTrackFake(object, sizeof(glhckTexture) + size); /* FIXME: downscale and give warning about it * for now just throw big fat error! */ if (twidth > GLHCKRF()->texture.maxTextureSize || theight > GLHCKRF()->texture.maxTextureSize || tdepth > GLHCKRF()->texture.maxTextureSize) { DEBUG(GLHCK_DBG_ERROR, "TEXTURE IS BIGGER THAN MAX TEXTURE SIZE (%d)", GLHCKRF()->texture.maxTextureSize); } DEBUG(GLHCK_DBG_CRAP, "NEW(%p:%u) %dx%dx%d %.2f MiB", object, object->object, object->internalWidth, object->internalHeight, object->internalDepth, (float)size/1048576); RET(0, "%d", RETURN_OK); return RETURN_OK; fail: RET(0, "%d", RETURN_FAIL); return RETURN_FAIL; } /* \brief recreate texture with new data. * dimensions of texture must be the same. */ GLHCKAPI int glhckTextureRecreate(glhckTexture *object, glhckTextureFormat format, glhckDataType type, int size, const void *data) { /* check the true data size, if not provided */ if (!size) { size = _glhckSizeForTexture(object->target, object->width, object->height, object->depth, format, type); } return glhckTextureCreate(object, object->target, 0, object->internalWidth, object->internalHeight, object->internalDepth, 0, format, type, size, data); } /* \brief fill subdata to texture */ GLHCKAPI void glhckTextureFill(glhckTexture *object, int level, int x, int y, int z, int width, int height, int depth, glhckTextureFormat format, glhckDataType type, int size, const void *data) { glhckTexture *old; CALL(2, "%p, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %p", object, level, x, y, z, width, height, depth, format, type, size, data); assert(object); assert(level >= 0); if (x + width > object->width) { DEBUG(GLHCK_DBG_ERROR, "x + width > texture width!"); return; } if (y + height > object->height) { DEBUG(GLHCK_DBG_ERROR, "h + height > texture height!"); return; } if (z + depth > object->depth) { DEBUG(GLHCK_DBG_ERROR, "z + depth > texture depth!"); return; } old = glhckTextureCurrentForTarget(object->target); glhckTextureBind(object); GLHCKRA()->textureFill(object->target, level, x, y, z, width, height, depth, format, type, size, data); if (old) glhckTextureBind(old); }