Texture_t *texture_loadFromPng(const char *aPath, bool aRepeatHorizontal, bool aRepeatVertical) { Texture_t *out = obj_create_autoreleased(&Class_Texture); out->displayCallback = (RenderableDisplayCallback_t)&_texture_draw; Png_t *png = png_load(aPath); if(!png) { dynamo_log("Unable to load png file from %s", aPath); return NULL; } glGenTextures(1, &out->id); glBindTexture(GL_TEXTURE_2D, out->id); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, png->hasAlpha ? GL_RGBA : GL_RGB, png->width, png->height, 0, png->hasAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, png->data); glError() glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aRepeatHorizontal ? GL_REPEAT : GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aRepeatVertical ? GL_REPEAT : GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Mipmaps can only be generated if the texture size is a power of 2 if(_isPowerOfTwo(png->width) && _isPowerOfTwo(png->height) && !aRepeatHorizontal && !aRepeatVertical) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glGenerateMipmap(GL_TEXTURE_2D); } else { dynamo_assert(!( (!_isPowerOfTwo(png->width) || !_isPowerOfTwo(png->height)) && (aRepeatHorizontal || aRepeatVertical) ), "Repeating textures must have power of 2 dimensions"); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } glError() out->size = vec2_create(png->width, png->height); out->pxAlignInset = vec2_create( (1.0f/out->size.w) * 0.5, (1.0f/out->size.h) * 0.5 ); return out; }
PARCRingBuffer1x1 * parcRingBuffer1x1_Create(uint32_t elements, RingBufferEntryDestroyer *destroyer) { assertTrue(_isPowerOfTwo(elements), "Parameter elements must be a power of 2, got %u", elements); return _create(elements, destroyer); }