12#include "physfsrwops.h"
33typedef struct glTexList_ {
50static int SDL_IsTrans( SDL_Surface* s,
int x,
int y );
51static uint8_t*
SDL_MapTrans( SDL_Surface* s,
int w,
int h );
52static size_t gl_transSize(
const int w,
const int h );
55static GLuint
gl_loadSurface( SDL_Surface* surface,
unsigned int flags,
int freesur );
76 bpp = s->format->BytesPerPixel;
78 p = (Uint8 *)s->pixels + y*s->pitch + x*bpp;
87 memcpy(&pixelcolour, p,
sizeof(Uint16));
91#if SDL_BYTEORDER == SDL_BIG_ENDIAN
92 pixelcolour = p[0] << 16 | p[1] << 8 | p[2];
94 pixelcolour = p[0] | p[1] << 8 | p[2] << 16;
99 memcpy(&pixelcolour, p,
sizeof(Uint32));
104 return ((pixelcolour & s->format->Amask) < (Uint32)(0.1*(
double)s->format->Amask));
130 size = gl_transSize(w, h);
133 WARN(_(
"Out of Memory"));
139 for (
int i=0; i<h; i++)
140 for (
int j=0; j<w; j++)
141 t[(i*w+j)/8] |= (
SDL_IsTrans(s,j,i)) ? 0 : (1<<((i*w+j)%8));
153static size_t gl_transSize(
const int w,
const int h )
156 return w*h/8 + ((w*h%8)?1:0);
167 glGenTextures( 1, &texture );
168 glBindTexture( GL_TEXTURE_2D, texture );
173 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
174 if (flags & OPENGL_TEX_MIPMAPS)
175 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
177 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
180 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
181 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
185 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
186 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
203int gl_fboCreate( GLuint *fbo, GLuint *tex, GLsizei width, GLsizei height )
208 glGenTextures(1, tex);
209 glBindTexture(GL_TEXTURE_2D, *tex);
210 glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
211 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
213 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
214 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
215 glBindTexture(GL_TEXTURE_2D, 0);
218 glGenFramebuffers( 1, fbo );
219 glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
222 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *tex, 0);
225 status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
226 if (status != GL_FRAMEBUFFER_COMPLETE)
227 WARN(_(
"Error setting up framebuffer!"));
234 return (status==GL_FRAMEBUFFER_COMPLETE);
237glTexture* gl_loadImageData(
float *data,
int w,
int h,
int sx,
int sy,
const char* name )
242 texture->w = (double) w;
243 texture->h = (double) h;
244 texture->sx = (double) sx;
245 texture->sy = (double) sy;
251 glTexImage2D( GL_TEXTURE_2D, 0, GL_SRGB_ALPHA, w, h, 0, GL_RGBA, GL_FLOAT, data );
252 glBindTexture( GL_TEXTURE_2D, 0 );
258 texture->sw = texture->w / texture->sx;
259 texture->sh = texture->h / texture->sy;
260 texture->srw = texture->sw / texture->w;
261 texture->srh = texture->sh / texture->h;
265 texture->name = strdup(name);
280static GLuint
gl_loadSurface( SDL_Surface* surface,
unsigned int flags,
int freesur )
289 SDL_LockSurface( surface );
290 glPixelStorei( GL_UNPACK_ALIGNMENT,
MIN( surface->pitch&-surface->pitch, 8 ) );
291 glTexImage2D( GL_TEXTURE_2D, 0, GL_SRGB_ALPHA,
292 surface->w, surface->h, 0, surface->format->Amask ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, surface->pixels );
293 SDL_UnlockSurface( surface );
296 if (flags & OPENGL_TEX_MIPMAPS) {
298 if (GLAD_GL_ARB_texture_filter_anisotropic) {
299 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, ¶m);
300 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, param);
302 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
303 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 9);
306 glGenerateMipmap(GL_TEXTURE_2D);
311 SDL_FreeSurface( surface );
332 unsigned int flags,
int w,
int h,
int sx,
int sy,
int freesur )
335 size_t filesize, cachesize;
340 if ((name != NULL) && !(flags & OPENGL_TEX_SKIPCACHE)) {
342 if ((texture != NULL) && (texture->trans != NULL)) {
344 SDL_FreeSurface( surface );
349 if (flags & OPENGL_TEX_MAPTRANS)
350 flags ^= OPENGL_TEX_MAPTRANS;
353 cachesize = gl_transSize(w, h);
362 md5_byte_t *md5val = malloc(16);
365 pngsize = SDL_RWseek( rw, 0, SEEK_END );
366 SDL_RWseek( rw, 0, SEEK_SET );
368 data = malloc(pngsize);
370 WARN(_(
"Out of Memory"));
372 SDL_RWread( rw, data, pngsize, 1 );
373 md5_append( &md5, (md5_byte_t*)data, pngsize );
376 md5_finish( &md5, md5val );
378 for (
int i=0; i<16; i++)
379 snprintf( &digest[i * 2], 3,
"%02x", md5val[i] );
382 asprintf( &cachefile,
"%scollisions/%s",
390 if (trans != NULL && cachesize != (
unsigned int)filesize) {
405 WARN(_(
"Texture '%s' has no RWops"), name);
409 SDL_LockSurface(surface);
411 SDL_UnlockSurface(surface);
413 if (cachefile != NULL) {
416 snprintf( dirpath,
sizeof(dirpath),
"%s/%s",
nfile_cachePath(),
"collisions/" );
424 texture =
gl_loadImagePad( name, surface, flags, w, h, sx, sy, freesur );
426 SDL_FreeSurface( surface );
427 texture->trans = trans;
445 unsigned int flags,
int w,
int h,
int sx,
int sy,
int freesur )
450 if ((name != NULL) && !(flags & OPENGL_TEX_SKIPCACHE)) {
456 if (flags & OPENGL_TEX_MAPTRANS)
461 texture = calloc( 1,
sizeof(
glTexture) );
463 texture->w = (double) w;
464 texture->h = (double) h;
465 texture->sx = (double) sx;
466 texture->sy = (double) sy;
470 texture->sw = texture->w / texture->sx;
471 texture->sh = texture->h / texture->sy;
472 texture->srw = texture->sw / texture->w;
473 texture->srh = texture->sh / texture->h;
474 texture->flags = flags;
477 texture->name = strdup(name);
481 texture->name = NULL;
495 return gl_loadImagePad( NULL, surface, flags, surface->w, surface->h, 1, 1, 1 );
520 if (strcmp(path,cur->tex->name)!=0)
523 if ((cur->sx!=sx) || (cur->sy!=sy))
552 while (last->
next != NULL)
573 if (!(flags & OPENGL_TEX_SKIPCACHE)) {
598 if (!(flags & OPENGL_TEX_SKIPCACHE)) {
621 WARN(_(
"Trying to load image from NULL path."));
626 rw = PHYSFSRWOPS_openRead( path );
628 WARN(_(
"Failed to load surface '%s' from ndata."), path);
649 SDL_Surface *surface;
655 surface = IMG_Load_RW( rw, 0 );
656 flags |= OPENGL_TEX_VFLIP;
657 if (surface == NULL) {
658 WARN(_(
"Unable to load image '%s'."), path );
662 if (surface == NULL) {
663 WARN(_(
"'%s' could not be opened"), path );
667 if (flags & OPENGL_TEX_MAPTRANS)
670 texture =
gl_loadImagePad( path, surface, flags, surface->w, surface->h, 1, 1, 1 );
685 const unsigned int flags )
690 if (!(flags & OPENGL_TEX_SKIPCACHE)) {
697 texture =
gl_newImage( path, flags | OPENGL_TEX_SKIPCACHE );
703 texture->sx = (double) sx;
704 texture->sy = (double) sy;
705 texture->sw = texture->w / texture->sx;
706 texture->sh = texture->h / texture->sy;
707 texture->srw = texture->sw / texture->w;
708 texture->srh = texture->sh / texture->h;
723 const int sx,
const int sy,
const unsigned int flags )
728 if (!(flags & OPENGL_TEX_SKIPCACHE)) {
741 texture->sx = (double) sx;
742 texture->sy = (double) sy;
743 texture->sw = texture->w / texture->sx;
744 texture->sh = texture->h / texture->sy;
745 texture->srw = texture->sw / texture->w;
746 texture->srh = texture->sh / texture->h;
765 if (cur->tex == texture) {
767 if (cur->used <= 0) {
769 glDeleteTextures( 1, &texture->texture );
770 free(texture->trans);
776 if (cur->next != NULL)
782 last->
next = cur->next;
791 if (texture->name != NULL)
792 WARN(_(
"Attempting to free texture '%s' not found in stack!"), texture->name);
795 glDeleteTextures( 1, &texture->texture );
796 free(texture->trans);
818 if (texture == cur->tex) {
826 WARN(_(
"Unable to duplicate texture '%s'."), texture->name);
841 int i = y*(int)(t->
w) + x ;
843 return !(t->
trans[ i/8 ] & (1 << (i%8)));
863 if ((dir > 2.*M_PI) || (dir < 0.)) {
864 WARN(_(
"Angle not between 0 and 2.*M_PI [%f]."), dir);
871 shard = 2.*M_PI / (t->
sy*t->
sx);
874 rdir = dir + shard/2.;
877 s = (int)(rdir / shard);
925 DEBUG(_(
"Texture leak detected!"));
927 DEBUG( n_(
" '%s' opened %d time",
" '%s' opened %d times", tex->used ), tex->tex->name, tex->used );
944 tex = realloc( tex, (*n)*
sizeof(
glTexture*) );
Provides macros to work with dynamic arrays.
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Header file with generic functions and naev-specifics.
int nfile_writeFile(const char *data, size_t len, const char *path)
Tries to write a file.
char * nfile_readFile(size_t *filesize, const char *path)
Tries to read a file.
int nfile_dirMakeExist(const char *path)
Creates a directory if it doesn't exist.
const char * nfile_cachePath(void)
Gets Naev's cache path (for cached data such as generated textures)
int nfile_fileExists(const char *path)
Checks to see if a file exists.
int asprintf(char **strp, const char *fmt,...)
Like sprintf(), but it allocates a large-enough string and returns the pointer in the first argument....
glTexture * gl_dupTexture(const glTexture *texture)
Duplicates a texture.
glTexture * gl_newSprite(const char *path, const int sx, const int sy, const unsigned int flags)
Loads the texture immediately, but also sets it as a sprite.
void gl_exitTextures(void)
Cleans up the opengl texture subsystem.
glTexture * gl_newImageRWops(const char *path, SDL_RWops *rw, const unsigned int flags)
Loads an image as a texture.
int gl_fboCreate(GLuint *fbo, GLuint *tex, GLsizei width, GLsizei height)
Creates a framebuffer and its associated texture.
static glTexture * gl_texExists(const char *path, int sx, int sy)
Check to see if a texture matching a path already exists.
glTexture * gl_loadImage(SDL_Surface *surface, unsigned int flags)
Loads the SDL_Surface to a glTexture.
glTexture * gl_newSpriteRWops(const char *path, SDL_RWops *rw, const int sx, const int sy, const unsigned int flags)
Loads the texture immediately, but also sets it as a sprite.
glTexture ** gl_copyTexArray(glTexture **tex, int *n)
Copy a texture array.
int gl_isTrans(const glTexture *t, const int x, const int y)
Checks to see if a pixel is transparent in a texture.
static glTexture * gl_loadNewImage(const char *path, unsigned int flags)
Only loads the image, does not add to stack unlike gl_newImage.
static int SDL_IsTrans(SDL_Surface *s, int x, int y)
Checks to see if a position of the surface is transparent.
glTexture ** gl_addTexArray(glTexture **tex, int *n, glTexture *t)
Adds an element to a texture array.
static int gl_texAdd(glTexture *tex, int sx, int sy)
Adds a texture to the list under the name of path.
glTexture * gl_loadImagePad(const char *name, SDL_Surface *surface, unsigned int flags, int w, int h, int sx, int sy, int freesur)
Loads the already padded SDL_Surface to a glTexture.
glTexture * gl_loadImagePadTrans(const char *name, SDL_Surface *surface, SDL_RWops *rw, unsigned int flags, int w, int h, int sx, int sy, int freesur)
Wrapper for gl_loadImagePad that includes transparency mapping.
glTexture * gl_newImage(const char *path, const unsigned int flags)
Loads an image as a texture.
static uint8_t * SDL_MapTrans(SDL_Surface *s, int w, int h)
Maps the surface transparency.
void gl_getSpriteFromDir(int *x, int *y, const glTexture *t, const double dir)
Sets x and y to be the appropriate sprite for glTexture using dir.
static glTexture * gl_loadNewImageRWops(const char *path, SDL_RWops *rw, unsigned int flags)
Only loads the image, does not add to stack unlike gl_newImage.
static GLuint gl_texParameters(unsigned int flags)
Sets default texture parameters.
static glTexList * texture_list
static GLuint gl_loadSurface(SDL_Surface *surface, unsigned int flags, int freesur)
Loads a surface into an opengl texture.
void gl_freeTexture(glTexture *texture)
Frees a texture.
int gl_initTextures(void)
Initializes the opengl texture subsystem.
Represents a node in the texture list.
Abstraction for rendering sprite sheets.
Define the state of the MD5 Algorithm.