diff --git a/Makefile b/Makefile index 1a57e403a0..cd817815e5 100644 --- a/Makefile +++ b/Makefile @@ -104,7 +104,7 @@ ifeq ($(HAVE_RGUI), 1) DEFINES += -DHAVE_MENU HAVE_MENU_COMMON = 1 ifeq ($(HAVE_LAKKA), 1) - OBJ += frontend/menu/disp/png_texture_load.o frontend/menu/backend/menu_lakka_backend.o frontend/menu/disp/lakka.o + OBJ += frontend/menu/backend/menu_lakka_backend.o frontend/menu/disp/lakka.o DEFINES += -DHAVE_LAKKA LIBS += -lpng endif diff --git a/frontend/menu/disp/lakka.c b/frontend/menu/disp/lakka.c index d6c0ce82e5..95a4ce2462 100644 --- a/frontend/menu/disp/lakka.c +++ b/frontend/menu/disp/lakka.c @@ -41,7 +41,7 @@ #include "../../../gfx/fonts/bitmap.h" #include "lakka.h" -#include "png_texture_load.h" +#include #define HSPACING 300 #define VSPACING 75 @@ -812,6 +812,161 @@ static void lakka_frame(void *data) gl_set_viewport(gl, gl->win_width, gl->win_height, false, false); } +// thanks to https://github.com/DavidEGrayson/ahrs-visualizer/blob/master/png_texture.cpp +static GLuint png_texture_load(const char * file_name, int * width, int * height) +{ + png_byte header[8]; + + FILE *fp = fopen(file_name, "rb"); + if (fp == 0) + { + perror(file_name); + return 0; + } + + // read the header + fread(header, 1, 8, fp); + + if (png_sig_cmp(header, 0, 8)) + { + fprintf(stderr, "error: %s is not a PNG.\n", file_name); + fclose(fp); + return 0; + } + + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + { + fprintf(stderr, "error: png_create_read_struct returned 0.\n"); + fclose(fp); + return 0; + } + + // create png info struct + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + fprintf(stderr, "error: png_create_info_struct returned 0.\n"); + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); + fclose(fp); + return 0; + } + + // create png info struct + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) + { + fprintf(stderr, "error: png_create_info_struct returned 0.\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + fclose(fp); + return 0; + } + + // the code in this if statement gets called if libpng encounters an error + if (setjmp(png_jmpbuf(png_ptr))) { + fprintf(stderr, "error from libpng\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(fp); + return 0; + } + + // init png reading + png_init_io(png_ptr, fp); + + // let libpng know you already read the first 8 bytes + png_set_sig_bytes(png_ptr, 8); + + // read all the info up to the image data + png_read_info(png_ptr, info_ptr); + + // variables to pass to get info + int bit_depth, color_type; + png_uint_32 temp_width, temp_height; + + // get info about png + png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, + NULL, NULL, NULL); + + if (width){ *width = temp_width; } + if (height){ *height = temp_height; } + + //printf("%s: %lux%lu %d\n", file_name, temp_width, temp_height, color_type); + + if (bit_depth != 8) + { + fprintf(stderr, "%s: Unsupported bit depth %d. Must be 8.\n", file_name, bit_depth); + return 0; + } + + GLint format; + switch(color_type) + { + case PNG_COLOR_TYPE_RGB: + format = GL_RGB; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + format = GL_RGBA; + break; + default: + fprintf(stderr, "%s: Unknown libpng color type %d.\n", file_name, color_type); + return 0; + } + + // Update the png info struct. + png_read_update_info(png_ptr, info_ptr); + + // Row size in bytes. + int rowbytes = png_get_rowbytes(png_ptr, info_ptr); + + // glTexImage2d requires rows to be 4-byte aligned + rowbytes += 3 - ((rowbytes-1) % 4); + + // Allocate the image_data as a big block, to be given to opengl + png_byte * image_data = (png_byte *)malloc(rowbytes * temp_height * sizeof(png_byte)+15); + if (image_data == NULL) + { + fprintf(stderr, "error: could not allocate memory for PNG image data\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(fp); + return 0; + } + + // row_pointers is for pointing to image_data for reading the png with libpng + png_byte ** row_pointers = (png_byte **)malloc(temp_height * sizeof(png_byte *)); + if (row_pointers == NULL) + { + fprintf(stderr, "error: could not allocate memory for PNG row pointers\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + free(image_data); + fclose(fp); + return 0; + } + + // set the individual row_pointers to point at the correct offsets of image_data + for (unsigned int i = 0; i < temp_height; i++) + { + row_pointers[temp_height - 1 - i] = image_data + i * rowbytes; + } + + // read the png into image_data through row_pointers + png_read_image(png_ptr, row_pointers); + + // Generate the OpenGL texture object + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, format, temp_width, temp_height, 0, format, GL_UNSIGNED_BYTE, image_data); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // clean up + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + free(image_data); + free(row_pointers); + fclose(fp); + return texture; +} + static void lakka_init_assets(void *data) { char path[256], dirpath[256];; diff --git a/frontend/menu/disp/png_texture_load.c b/frontend/menu/disp/png_texture_load.c deleted file mode 100644 index 69b0945566..0000000000 --- a/frontend/menu/disp/png_texture_load.c +++ /dev/null @@ -1,172 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2013 - Hans-Kristian Arntzen - * Copyright (C) 2011-2013 - Daniel De Matteis - * - * RetroArch is free software: you can redistribute it and/or modify it under the terms - * of the GNU General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with RetroArch. - * If not, see . - */ - -#include "png_texture_load.h" - -// thanks to https://github.com/DavidEGrayson/ahrs-visualizer/blob/master/png_texture.cpp -GLuint png_texture_load(const char * file_name, int * width, int * height) -{ - png_byte header[8]; - - FILE *fp = fopen(file_name, "rb"); - if (fp == 0) - { - perror(file_name); - return 0; - } - - // read the header - fread(header, 1, 8, fp); - - if (png_sig_cmp(header, 0, 8)) - { - fprintf(stderr, "error: %s is not a PNG.\n", file_name); - fclose(fp); - return 0; - } - - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) - { - fprintf(stderr, "error: png_create_read_struct returned 0.\n"); - fclose(fp); - return 0; - } - - // create png info struct - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - fprintf(stderr, "error: png_create_info_struct returned 0.\n"); - png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); - fclose(fp); - return 0; - } - - // create png info struct - png_infop end_info = png_create_info_struct(png_ptr); - if (!end_info) - { - fprintf(stderr, "error: png_create_info_struct returned 0.\n"); - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); - fclose(fp); - return 0; - } - - // the code in this if statement gets called if libpng encounters an error - if (setjmp(png_jmpbuf(png_ptr))) { - fprintf(stderr, "error from libpng\n"); - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - fclose(fp); - return 0; - } - - // init png reading - png_init_io(png_ptr, fp); - - // let libpng know you already read the first 8 bytes - png_set_sig_bytes(png_ptr, 8); - - // read all the info up to the image data - png_read_info(png_ptr, info_ptr); - - // variables to pass to get info - int bit_depth, color_type; - png_uint_32 temp_width, temp_height; - - // get info about png - png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, - NULL, NULL, NULL); - - if (width){ *width = temp_width; } - if (height){ *height = temp_height; } - - //printf("%s: %lux%lu %d\n", file_name, temp_width, temp_height, color_type); - - if (bit_depth != 8) - { - fprintf(stderr, "%s: Unsupported bit depth %d. Must be 8.\n", file_name, bit_depth); - return 0; - } - - GLint format; - switch(color_type) - { - case PNG_COLOR_TYPE_RGB: - format = GL_RGB; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - format = GL_RGBA; - break; - default: - fprintf(stderr, "%s: Unknown libpng color type %d.\n", file_name, color_type); - return 0; - } - - // Update the png info struct. - png_read_update_info(png_ptr, info_ptr); - - // Row size in bytes. - int rowbytes = png_get_rowbytes(png_ptr, info_ptr); - - // glTexImage2d requires rows to be 4-byte aligned - rowbytes += 3 - ((rowbytes-1) % 4); - - // Allocate the image_data as a big block, to be given to opengl - png_byte * image_data = (png_byte *)malloc(rowbytes * temp_height * sizeof(png_byte)+15); - if (image_data == NULL) - { - fprintf(stderr, "error: could not allocate memory for PNG image data\n"); - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - fclose(fp); - return 0; - } - - // row_pointers is for pointing to image_data for reading the png with libpng - png_byte ** row_pointers = (png_byte **)malloc(temp_height * sizeof(png_byte *)); - if (row_pointers == NULL) - { - fprintf(stderr, "error: could not allocate memory for PNG row pointers\n"); - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - free(image_data); - fclose(fp); - return 0; - } - - // set the individual row_pointers to point at the correct offsets of image_data - for (unsigned int i = 0; i < temp_height; i++) - { - row_pointers[temp_height - 1 - i] = image_data + i * rowbytes; - } - - // read the png into image_data through row_pointers - png_read_image(png_ptr, row_pointers); - - // Generate the OpenGL texture object - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, format, temp_width, temp_height, 0, format, GL_UNSIGNED_BYTE, image_data); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // clean up - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - free(image_data); - free(row_pointers); - fclose(fp); - return texture; -} \ No newline at end of file diff --git a/frontend/menu/disp/png_texture_load.h b/frontend/menu/disp/png_texture_load.h deleted file mode 100644 index e06cb67102..0000000000 --- a/frontend/menu/disp/png_texture_load.h +++ /dev/null @@ -1,21 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2013 - Hans-Kristian Arntzen - * Copyright (C) 2011-2013 - Daniel De Matteis - * - * RetroArch is free software: you can redistribute it and/or modify it under the terms - * of the GNU General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with RetroArch. - * If not, see . - */ - -#include "../../../gfx/gl_common.h" -#include "../../../gfx/gfx_common.h" -#include - -GLuint png_texture_load(const char *, int *, int *); \ No newline at end of file