diff --git a/gfx/fonts/freetype.c b/gfx/fonts/freetype.c index a45897b085..37149c00c8 100644 --- a/gfx/fonts/freetype.c +++ b/gfx/fonts/freetype.c @@ -127,17 +127,12 @@ static void calculate_msg_geometry(const struct font_output *head, struct font_r rect->height = y_max - y_min; } -// TODO: Doesn't really use PBO ... static void adjust_power_of_two(gl_t *gl, struct font_rect *geom) { // Some systems really hate NPOT textures. geom->pot_width = next_pow2(geom->width); geom->pot_height = next_pow2(geom->height); -#ifdef HAVE_GL_PBO - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); -#endif - if ((geom->pot_width > gl->font_tex_w) || (geom->pot_height > gl->font_tex_h)) { gl->font_tex_empty_buf = realloc(gl->font_tex_empty_buf, geom->pot_width * geom->pot_height); @@ -152,24 +147,16 @@ static void adjust_power_of_two(gl_t *gl, struct font_rect *geom) gl->font_tex_h = geom->pot_height; } -#ifdef HAVE_GL_PBO glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl->pbo); -#endif } // Old style "blitting", so we can render all the fonts in one go. // TODO: Is it possible that fonts could overlap if we blit without alpha blending? static void blit_fonts(gl_t *gl, const struct font_output *head, const struct font_rect *geom) { -#ifdef HAVE_GL_PBO - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); -#endif - // Clear out earlier fonts. glPixelStorei(GL_UNPACK_ALIGNMENT, 8); - glPixelStorei(GL_UNPACK_ROW_LENGTH, gl->font_tex_w); - + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, gl->font_tex_w, gl->font_tex_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, gl->font_tex_empty_buf); @@ -190,10 +177,7 @@ static void blit_fonts(gl_t *gl, const struct font_output *head, const struct fo head = head->next; } -#ifdef HAVE_GL_PBO glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl->pbo); -#endif } static void calculate_font_coords(gl_t *gl, diff --git a/gfx/gl.c b/gfx/gl.c index 79c868e5a3..99503ba620 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -130,16 +130,31 @@ static bool load_fbo_proc(void) { return true; } #endif #ifdef _WIN32 -PFNGLCLIENTACTIVETEXTUREPROC pglClientActiveTexture = NULL; -PFNGLACTIVETEXTUREPROC pglActiveTexture = NULL; -static inline bool load_gl_proc(void) +PFNGLCLIENTACTIVETEXTUREPROC pglClientActiveTexture; +PFNGLACTIVETEXTUREPROC pglActiveTexture; +static PFNGLBINDBUFFERPROC pglBindBuffer; +static PFNGLBUFFERSUBDATA pglBufferSubData; +static PFNGLBUFFERDATA pglBufferData; +static PFNGLMAPBUFFER pglMapBuffer; +static PFNGLUNMAPBUFFER pglUnmapBuffer; +static inline bool load_gl_proc_win32(void) { LOAD_SYM(glClientActiveTexture); LOAD_SYM(glActiveTexture); - return pglClientActiveTexture && pglActiveTexture; + LOAD_SYM(glBindBuffer); + LOAD_SYM(glBufferSubData); + LOAD_SYM(glBufferData); + LOAD_SYM(glMapBuffer); + LOAD_SYM(glUnmapBuffer); + return pglClientActiveTexture && pglActiveTexture && pglBindBuffer && + pglBufferSubData && pglBufferData && pglMapBuffer && pglUnmapBuffer; } #else -static inline bool load_gl_proc(void) { return true; } +#define pglBindBuffer glBindBuffer +#define pglBufferSubData glBufferSubData +#define pglBufferData glBufferData +#define pglMapBuffer glMapBuffer +#define pglUnmapBuffer glUnmapBuffer #endif ////////////////// Shaders @@ -348,10 +363,6 @@ static void gl_compute_fbo_geometry(gl_t *gl, unsigned width, unsigned height, static void gl_create_fbo_textures(gl_t *gl) { -#ifdef HAVE_GL_PBO - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); -#endif - glGenTextures(gl->fbo_pass, gl->fbo_texture); GLuint base_filt = g_settings.video.second_pass_smooth ? GL_LINEAR : GL_NEAREST; @@ -383,10 +394,6 @@ static void gl_create_fbo_textures(gl_t *gl) } glBindTexture(GL_TEXTURE_2D, 0); - -#ifdef HAVE_GL_PBO - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl->pbo); -#endif } static bool gl_create_fbo_targets(gl_t *gl) @@ -667,19 +674,11 @@ static void gl_check_fbo_dimensions(gl_t *gl) pglBindFramebuffer(GL_FRAMEBUFFER, gl->fbo[i]); glBindTexture(GL_TEXTURE_2D, gl->fbo_texture[i]); -#ifdef HAVE_GL_PBO - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); -#endif - glTexImage2D(GL_TEXTURE_2D, 0, RARCH_GL_INTERNAL_FORMAT, gl->fbo_rect[i].width, gl->fbo_rect[i].height, 0, RARCH_GL_TEXTURE_TYPE, RARCH_GL_FORMAT32, NULL); -#ifdef HAVE_GL_PBO - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl->pbo); -#endif - pglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl->fbo_texture[i], 0); GLenum status = pglCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -804,17 +803,21 @@ static void gl_update_input_size(gl_t *gl, unsigned width, unsigned height, unsi gl->tex_w * gl->tex_h * gl->tex_index * gl->base_size, gl->tex_w * gl->tex_h * gl->base_size, gl->empty_buf); -#elif defined(HAVE_GL_PBO) - glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(gl->tex_w)); +#elif defined(HAVE_PBO) + pglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl->pbo); + glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, gl->tex_w * gl->tex_h * gl->base_size, gl->empty_buf); + glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(gl->tex_w * gl->base_size)); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, gl->tex_w, gl->tex_h, gl->texture_type, gl->texture_fmt, NULL); + + pglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); #else - glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(pitch)); - glPixelStorei(GL_UNPACK_ROW_LENGTH, gl->tex_w); + glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(width * gl->base_size)); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, gl->tex_w, gl->tex_h, gl->texture_type, gl->texture_fmt, gl->empty_buf); @@ -879,32 +882,35 @@ static void gl_init_textures(gl_t *gl) } glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]); } -#elif defined(HAVE_GL_PBO) +#elif defined(HAVE_PBO) static inline void gl_copy_frame(gl_t *gl, const void *frame, unsigned width, unsigned height, unsigned pitch) { const uint8_t *frame_copy = frame; size_t frame_copy_size = width * gl->base_size; - uint8_t *data = (uint8_t*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + pglBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl->pbo); + uint8_t *data = (uint8_t*)pglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); if (!data) return; for (unsigned h = 0; h < height; h++, data += frame_copy_size, frame_copy += pitch) memcpy(data, frame_copy, frame_copy_size); - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + pglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(width * gl->base_size)); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, gl->texture_type, gl->texture_fmt, NULL); + pglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); } static void gl_init_textures(gl_t *gl) { - void *buf = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + void *buf = pglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); if (buf) { memset(buf, 0, gl->tex_w * gl->tex_h * gl->base_size); - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + pglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); } glGenTextures(TEXTURES, gl->texture); @@ -932,10 +938,12 @@ static void gl_init_textures(gl_t *gl) #else static inline void gl_copy_frame(gl_t *gl, const void *frame, unsigned width, unsigned height, unsigned pitch) { + glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(width * gl->base_size)); glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / gl->base_size); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, gl->texture_type, gl->texture_fmt, frame); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } static void gl_init_textures(gl_t *gl) @@ -950,7 +958,7 @@ static void gl_init_textures(gl_t *gl) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl->tex_filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl->tex_filter); - glPixelStorei(GL_UNPACK_ROW_LENGTH, gl->tex_w); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_2D, 0, RARCH_GL_INTERNAL_FORMAT, gl->tex_w, gl->tex_h, 0, gl->texture_type, gl->texture_fmt, gl->empty_buf ? gl->empty_buf : NULL); @@ -1096,7 +1104,7 @@ static void gl_free(void *data) #ifdef HAVE_OPENGL_TEXREF glBindBuffer(GL_TEXTURE_REFERENCE_BUFFER_SCE, 0); glDeleteBuffers(1, &gl->pbo); -#elif defined(HAVE_GL_PBO) +#elif defined(HAVE_PBO) glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glDeleteBuffers(1, &gl->pbo); #endif @@ -1170,9 +1178,9 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo #endif #ifdef _WIN32 - // Win32 GL lib doesn't have some functions needed. + // Win32 GL lib doesn't have some elementary functions needed. // Need to load dynamically :( - if (!load_gl_proc()) + if (!load_gl_proc_win32()) { gfx_ctx_destroy(); free(gl); @@ -1180,6 +1188,17 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo } #endif +#ifdef HAVE_PBO + RARCH_LOG("[GL]: Using PBOs.\n"); + if (!gl_query_extension("GL_ARB_pixel_buffer_object")) + { + RARCH_ERR("[GL]: PBOs are enabled, but extension does not exist ...\n"); + gfx_ctx_destroy(); + free(gl); + return NULL; + } +#endif + gl->vsync = video->vsync; gl->fullscreen = video->fullscreen; @@ -1250,7 +1269,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo glBindBuffer(GL_TEXTURE_REFERENCE_BUFFER_SCE, gl->pbo); glBufferData(GL_TEXTURE_REFERENCE_BUFFER_SCE, gl->tex_w * gl->tex_h * gl->base_size * TEXTURES, NULL, GL_STREAM_DRAW); -#elif defined(HAVE_GL_PBO) +#elif defined(HAVE_PBO) glGenBuffers(1, &gl->pbo); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl->pbo); glBufferData(GL_PIXEL_UNPACK_BUFFER, @@ -1279,7 +1298,8 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo gfx_ctx_input_driver(input, input_data); gl_init_font(gl, g_settings.video.font_path, g_settings.video.font_size); - + + if (!gl_check_error()) { gfx_ctx_destroy(); @@ -1499,3 +1519,4 @@ const video_driver_t video_gl = { NULL, #endif }; + diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 51b88ef60a..66369e884a 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -24,6 +24,8 @@ #include "../config.h" #endif +#include + #if defined(__APPLE__) #include #include @@ -35,7 +37,6 @@ #include #include #include -#define GL_QUADS 0x0007 #elif defined(HAVE_OPENGLES2) #include #include @@ -48,6 +49,16 @@ #include #endif +static inline bool gl_query_extension(const char *ext) +{ + const char *str = (const char*)glGetString(GL_EXTENSIONS); + bool ret = str && strstr(str, ext); + RARCH_LOG("Querying GL extension: %s => %s\n", + ext, ret ? "exists" : "doesn't exist"); + + return ret; +} + static inline bool gl_check_error(void) { int error = glGetError(); @@ -57,18 +68,18 @@ static inline bool gl_check_error(void) RARCH_ERR("GL: Invalid enum.\n"); break; case GL_INVALID_VALUE: - RARCH_ERR("GL: Invalid value. (You're not alone.)\n"); + RARCH_ERR("GL: Invalid value.\n"); break; case GL_INVALID_OPERATION: RARCH_ERR("GL: Invalid operation.\n"); break; case GL_OUT_OF_MEMORY: - RARCH_ERR("GL: Out of memory. Harhar.\n"); + RARCH_ERR("GL: Out of memory.\n"); break; case GL_NO_ERROR: return true; default: - RARCH_ERR("Non specified error :v\n"); + RARCH_ERR("Non specified GL error.\n"); } return false; @@ -197,9 +208,7 @@ typedef struct gl struct gl_coords coords; -#if defined(__CELLOS_LV2__) || defined(HAVE_GL_PBO) GLuint pbo; -#endif GLenum texture_type; // XBGR1555 or ARGB GLenum texture_fmt; unsigned base_size; // 2 or 4 diff --git a/gfx/shader_cg.c b/gfx/shader_cg.c index 36ba6d68e3..4d66e73c9b 100644 --- a/gfx/shader_cg.c +++ b/gfx/shader_cg.c @@ -484,7 +484,7 @@ static void load_texture_data(GLuint *obj, const struct texture_image *img, bool 0, GL_ARGB_SCE, GL_UNSIGNED_INT_8_8_8_8, img->pixels); #else glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glPixelStorei(GL_UNPACK_ROW_LENGTH, img->width); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->width, img->height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, img->pixels); diff --git a/gfx/shader_glsl.c b/gfx/shader_glsl.c index b96db992fa..39e91e8fb9 100644 --- a/gfx/shader_glsl.c +++ b/gfx/shader_glsl.c @@ -380,7 +380,7 @@ static bool get_texture_image(const char *shader_path, xmlNodePtr ptr) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glPixelStorei(GL_UNPACK_ROW_LENGTH, img.width); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.width, img.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, img.pixels); diff --git a/qb/config.libs.sh b/qb/config.libs.sh index 982e8a8b30..195a6ed0b2 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -77,8 +77,10 @@ fi if [ "$OS" = Darwin ]; then check_lib FBO "-framework OpenGL" glFramebufferTexture2D + check_lib PBO "-framework OpenGL" glMapBuffer else check_lib FBO -lGL glFramebufferTexture2D + check_lib PBO -lGL glMapBuffer fi check_pkgconf RSOUND rsound 1.1 @@ -143,6 +145,6 @@ check_pkgconf PYTHON python3 add_define_make OS "$OS" # Creates config.mk and config.h. -VARS="ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO PULSE SDL OPENGL DYLIB GETOPT_LONG THREADS CG XML SDL_IMAGE LIBPNG DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL CONFIGFILE FREETYPE XVIDEO X11 XEXT NETPLAY NETWORK_CMD STDIN_CMD COMMAND SOCKET_LEGACY FBO STRL PYTHON FFMPEG_ALLOC_CONTEXT3 FFMPEG_AVCODEC_OPEN2 FFMPEG_AVIO_OPEN FFMPEG_AVFORMAT_WRITE_HEADER FFMPEG_AVFORMAT_NEW_STREAM FFMPEG_AVCODEC_ENCODE_AUDIO2 FFMPEG_AVCODEC_ENCODE_VIDEO2 SINC FIXED_POINT BSV_MOVIE RPI" +VARS="ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO PULSE SDL OPENGL DYLIB GETOPT_LONG THREADS CG XML SDL_IMAGE LIBPNG DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL CONFIGFILE FREETYPE XVIDEO X11 XEXT NETPLAY NETWORK_CMD STDIN_CMD COMMAND SOCKET_LEGACY FBO PBO STRL PYTHON FFMPEG_ALLOC_CONTEXT3 FFMPEG_AVCODEC_OPEN2 FFMPEG_AVIO_OPEN FFMPEG_AVFORMAT_WRITE_HEADER FFMPEG_AVFORMAT_NEW_STREAM FFMPEG_AVCODEC_ENCODE_AUDIO2 FFMPEG_AVCODEC_ENCODE_VIDEO2 SINC FIXED_POINT BSV_MOVIE RPI" create_config_make config.mk $VARS create_config_header config.h $VARS diff --git a/qb/config.params.sh b/qb/config.params.sh index fad2e7bcf7..88271cead6 100644 --- a/qb/config.params.sh +++ b/qb/config.params.sh @@ -9,6 +9,7 @@ HAVE_OPENGL=yes # Disable OpenGL support HAVE_CG=auto # Enable Cg shader support HAVE_XML=auto # Enable bSNES-style XML shader support HAVE_FBO=auto # Enable render-to-texture (FBO) support +HAVE_PBO=no # Enable pixel buffer object (PBO) support HAVE_ALSA=auto # Enable ALSA support HAVE_OSS=auto # Enable OSS support HAVE_RSOUND=auto # Enable RSound support