static bool gl_xml_shader(void *data, const char *path) { gl_t *gl = (gl_t*)data; #ifdef HAVE_FBO gl_deinit_fbo(gl); glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]); #endif gl_shader_deinit(); if (!gl_glsl_init(path)) return false; #ifdef HAVE_FBO // Set up render to texture again. gl_init_fbo(gl, gl->tex_w, gl->tex_h); #endif // Apparently need to set viewport for passes when we aren't using FBOs. gl_shader_use(0); gl_set_viewport(gl, gl->win_width, gl->win_height, false, true); gl_shader_use(1); gl_set_viewport(gl, gl->win_width, gl->win_height, false, true); return true; }
static void gfx_ctx_rmenu_frame(void *data) { gl_t *gl = (gl_t*)data; gl_shader_use(gl, RARCH_CG_MENU_SHADER_INDEX); gl_set_viewport(gl, gl->win_width, gl->win_height, true, false); if (gl->shader) { gl->shader->set_params(gl->win_width, gl->win_height, gl->win_width, gl->win_height, gl->win_width, gl->win_height, g_extern.frame_count, NULL, NULL, NULL, 0); } glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, menu_texture_id); gl->coords.vertex = vertexes_flipped; gl_shader_set_coords(gl, &gl->coords, &gl->mvp); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]); gl_set_viewport(gl, gl->win_width, gl->win_height, false, true); }
static void gl_render_msg(gl_t *gl, const char *msg) { if (!gl->font) return; GLfloat font_vertex[8]; GLfloat font_vertex_dark[8]; GLfloat font_tex_coords[8]; // Deactivate custom shaders. Enable the font texture. gl_shader_use(0); set_viewport(gl, gl->win_width, gl->win_height, false, false); glBindTexture(GL_TEXTURE_2D, gl->font_tex); glTexCoordPointer(2, GL_FLOAT, 0, font_tex_coords); // Need blending. // Using fixed function pipeline here since we cannot guarantee presence of shaders (would be kinda overkill anyways). glEnable(GL_BLEND); struct font_output_list out; // If we get the same message, there's obviously no need to render fonts again ... if (strcmp(gl->font_last_msg, msg) != 0) { font_renderer_msg(gl->font, msg, &out); struct font_output *head = out.head; struct font_rect geom; calculate_msg_geometry(head, &geom); adjust_power_of_two(gl, &geom); blit_fonts(gl, head, &geom); font_renderer_free_output(&out); strlcpy(gl->font_last_msg, msg, sizeof(gl->font_last_msg)); gl->font_last_width = geom.width; gl->font_last_height = geom.height; } calculate_font_coords(gl, font_vertex, font_vertex_dark, font_tex_coords); glVertexPointer(2, GL_FLOAT, 0, font_vertex_dark); glColorPointer(4, GL_FLOAT, 0, gl->font_color_dark); glDrawArrays(GL_QUADS, 0, 4); glVertexPointer(2, GL_FLOAT, 0, font_vertex); glColorPointer(4, GL_FLOAT, 0, gl->font_color); glDrawArrays(GL_QUADS, 0, 4); // Go back to old rendering path. glTexCoordPointer(2, GL_FLOAT, 0, gl->tex_coords); glVertexPointer(2, GL_FLOAT, 0, vertexes_flipped); glColorPointer(4, GL_FLOAT, 0, white_color); glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]); glDisable(GL_BLEND); set_projection(gl, true); }
static void gl_render_menu(gl_t *gl) { gl_shader_use(RARCH_CG_MENU_SHADER_INDEX); gl_shader_set_params(gl->win_width, gl->win_height, gl->win_width, gl->win_height, gl->win_width, gl->win_height, gl->frame_count, NULL, NULL, NULL, 0); gl_set_viewport(gl, gl->win_width, gl->win_height, true, false); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gl->menu_texture_id); glVertexPointer(2, GL_FLOAT, 0, default_vertex_ptr); glDrawArrays(GL_QUADS, 0, 4); glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]); }
static void setup_font(void *data, const char *msg, GLfloat scale, GLfloat pos_x, GLfloat pos_y) { gl_t *gl = (gl_t*)data; if (!gl->font) return; gl_shader_use(gl, 0); gl_set_viewport(gl, gl->win_width, gl->win_height, false, false); glEnable(GL_BLEND); GLfloat font_vertex[8]; GLfloat font_vertex_dark[8]; GLfloat font_tex_coords[8]; glBindTexture(GL_TEXTURE_2D, gl->font_tex); gl->coords.tex_coord = font_tex_coords; struct font_output_list out; // If we get the same message, there's obviously no need to render fonts again ... if (strcmp(gl->font_last_msg, msg) != 0) { gl->font_driver->render_msg(gl->font, msg, &out); struct font_output *head = out.head; struct font_rect geom; calculate_msg_geometry(head, &geom); adjust_power_of_two(gl, &geom); blit_fonts(gl, head, &geom); gl->font_driver->free_output(gl->font, &out); strlcpy(gl->font_last_msg, msg, sizeof(gl->font_last_msg)); gl->font_last_width = geom.width; gl->font_last_height = geom.height; } calculate_font_coords(gl, font_vertex, font_vertex_dark, font_tex_coords, scale, pos_x, pos_y); gl->coords.vertex = font_vertex_dark; gl->coords.color = gl->font_color_dark; gl_shader_set_coords(gl, &gl->coords, &gl->mvp); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); gl->coords.vertex = font_vertex; gl->coords.color = gl->font_color; gl_shader_set_coords(gl, &gl->coords, &gl->mvp); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // Post - Go back to old rendering path. gl->coords.vertex = vertexes_flipped; gl->coords.tex_coord = gl->tex_coords; gl->coords.color = white_color; glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]); glDisable(GL_BLEND); struct gl_ortho ortho = {0, 1, 0, 1, -1, 1}; gl_set_projection(gl, &ortho, true); }
int uterm_drm3d_display_fill(struct uterm_display *disp, uint8_t r, uint8_t g, uint8_t b, unsigned int x, unsigned int y, unsigned int width, unsigned int height) { struct uterm_drm3d_video *v3d; unsigned int sw, sh, tmp, i; float mat[16]; float vertices[6 * 2], colors[6 * 4]; int ret; v3d = uterm_drm_video_get_data(disp->video); ret = uterm_drm3d_display_use(disp, NULL); if (ret) return ret; ret = init_shaders(disp->video); if (ret) return ret; sw = uterm_drm_mode_get_width(disp->current_mode); sh = uterm_drm_mode_get_height(disp->current_mode); for (i = 0; i < 6; ++i) { colors[i * 4 + 0] = r / 255.0; colors[i * 4 + 1] = g / 255.0; colors[i * 4 + 2] = b / 255.0; colors[i * 4 + 3] = 1.0; } vertices[0] = -1.0; vertices[1] = -1.0; vertices[2] = -1.0; vertices[3] = +1.0; vertices[4] = +1.0; vertices[5] = +1.0; vertices[6] = -1.0; vertices[7] = -1.0; vertices[8] = +1.0; vertices[9] = +1.0; vertices[10] = +1.0; vertices[11] = -1.0; tmp = x + width; if (tmp < x || x >= sw) return -EINVAL; if (tmp > sw) width = sw - x; tmp = y + height; if (tmp < y || y >= sh) return -EINVAL; if (tmp > sh) height = sh - y; /* Caution: * opengl uses a coordinate system with the origin at _lower-left_ corner * and positive y-axis up, while other parts uses a coordinate system * with the origin at _upper-left_ corner and positive y-axis down. */ y = sh - y; // invert y-axis y -= height; // move origin to lower left corner glViewport(x, y, width, height); glDisable(GL_BLEND); gl_shader_use(v3d->fill_shader); gl_m4_identity(mat); glUniformMatrix4fv(v3d->uni_fill_proj, 1, GL_FALSE, mat); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glDrawArrays(GL_TRIANGLES, 0, 6); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); if (gl_has_error(v3d->fill_shader)) { log_warning("GL error"); return -EFAULT; } return 0; }
static int display_blend(struct uterm_display *disp, const struct uterm_video_buffer *buf, unsigned int x, unsigned int y, uint8_t fr, uint8_t fg, uint8_t fb, uint8_t br, uint8_t bg, uint8_t bb) { struct uterm_drm3d_video *v3d; unsigned int sw, sh, tmp, width, height, i; float mat[16]; float vertices[6 * 2], texpos[6 * 2], fgcol[3], bgcol[3]; int ret; uint8_t *packed, *src, *dst; if (!buf || buf->format != UTERM_FORMAT_GREY) return -EINVAL; v3d = uterm_drm_video_get_data(disp->video); ret = uterm_drm3d_display_use(disp, NULL); if (ret) return ret; ret = init_shaders(disp->video); if (ret) return ret; sw = uterm_drm_mode_get_width(disp->current_mode); sh = uterm_drm_mode_get_height(disp->current_mode); vertices[0] = -1.0; vertices[1] = -1.0; vertices[2] = -1.0; vertices[3] = +1.0; vertices[4] = +1.0; vertices[5] = +1.0; vertices[6] = -1.0; vertices[7] = -1.0; vertices[8] = +1.0; vertices[9] = +1.0; vertices[10] = +1.0; vertices[11] = -1.0; texpos[0] = 0.0; texpos[1] = 1.0; texpos[2] = 0.0; texpos[3] = 0.0; texpos[4] = 1.0; texpos[5] = 0.0; texpos[6] = 0.0; texpos[7] = 1.0; texpos[8] = 1.0; texpos[9] = 0.0; texpos[10] = 1.0; texpos[11] = 1.0; fgcol[0] = fr / 255.0; fgcol[1] = fg / 255.0; fgcol[2] = fb / 255.0; bgcol[0] = br / 255.0; bgcol[1] = bg / 255.0; bgcol[2] = bb / 255.0; tmp = x + buf->width; if (tmp < x || x >= sw) return -EINVAL; if (tmp > sw) width = sw - x; else width = buf->width; tmp = y + buf->height; if (tmp < y || y >= sh) return -EINVAL; if (tmp > sh) height = sh - y; else height = buf->height; glViewport(x, sh - y - height, width, height); glDisable(GL_BLEND); gl_shader_use(v3d->blend_shader); gl_m4_identity(mat); glUniformMatrix4fv(v3d->uni_blend_proj, 1, GL_FALSE, mat); glUniform3fv(v3d->uni_blend_fgcol, 1, fgcol); glUniform3fv(v3d->uni_blend_bgcol, 1, bgcol); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, v3d->tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); if (v3d->supports_rowlen) { glPixelStorei(GL_UNPACK_ROW_LENGTH, buf->stride); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buf->data); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } else if (buf->stride == width) { glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buf->data); } else { packed = malloc(width * height); if (!packed) return -ENOMEM; src = buf->data; dst = packed; for (i = 0; i < height; ++i) { memcpy(dst, src, width); dst += width; src += buf->stride; } glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, packed); free(packed); } glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glUniform1i(v3d->uni_blend_tex, 0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texpos); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glDrawArrays(GL_TRIANGLES, 0, 6); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); if (gl_has_error(v3d->blend_shader)) { log_warning("GL error"); return -EFAULT; } return 0; }
static void *gl_init(const video_info_t *video, const input_driver_t **input, void **input_data) { #ifdef _WIN32 gfx_set_dwm(); #endif #ifdef RARCH_CONSOLE if (driver.video_data) return driver.video_data; #endif gl_t *gl = (gl_t*)calloc(1, sizeof(gl_t)); if (!gl) return NULL; if (!gfx_ctx_init()) { free(gl); return NULL; } unsigned full_x = 0, full_y = 0; gfx_ctx_get_video_size(&full_x, &full_y); RARCH_LOG("Detecting resolution %ux%u.\n", full_x, full_y); gfx_ctx_set_swap_interval(video->vsync ? 1 : 0, false); unsigned win_width = video->width; unsigned win_height = video->height; if (video->fullscreen && (win_width == 0) && (win_height == 0)) { win_width = full_x; win_height = full_y; } if (!gfx_ctx_set_video_mode(win_width, win_height, g_settings.video.force_16bit ? 15 : 0, video->fullscreen)) { free(gl); return NULL; } #ifndef RARCH_CONSOLE gfx_ctx_update_window_title(true); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #endif #if (defined(HAVE_XML) || defined(HAVE_CG)) && defined(_WIN32) // Win32 GL lib doesn't have some functions needed for XML shaders. // Need to load dynamically :( if (!load_gl_proc()) { gfx_ctx_destroy(); free(gl); return NULL; } #endif gl->vsync = video->vsync; gl->fullscreen = video->fullscreen; gl->full_x = full_x; gl->full_y = full_y; gl->win_width = win_width; gl->win_height = win_height; RARCH_LOG("GL: Using resolution %ux%u\n", gl->win_width, gl->win_height); #if defined(HAVE_CG_MENU) && defined(RARCH_CONSOLE) RARCH_LOG("Initializing menu shader ...\n"); gl_cg_set_menu_shader(default_paths.menu_shader_file); #endif if (!gl_shader_init()) { RARCH_ERR("Shader init failed.\n"); gfx_ctx_destroy(); free(gl); return NULL; } RARCH_LOG("GL: Loaded %u program(s).\n", gl_shader_num()); #ifdef HAVE_FBO // Set up render to texture. gl_init_fbo(gl, RARCH_SCALE_BASE * video->input_scale, RARCH_SCALE_BASE * video->input_scale); #endif gl->keep_aspect = video->force_aspect; // Apparently need to set viewport for passes when we aren't using FBOs. gl_shader_use(0); gl_set_viewport(gl, gl->win_width, gl->win_height, false, true); gl_shader_use(1); gl_set_viewport(gl, gl->win_width, gl->win_height, false, true); bool force_smooth = false; if (gl_shader_filter_type(1, &force_smooth)) gl->tex_filter = force_smooth ? GL_LINEAR : GL_NEAREST; else gl->tex_filter = video->smooth ? GL_LINEAR : GL_NEAREST; gl->texture_type = RARCH_GL_TEXTURE_TYPE; gl->texture_fmt = video->rgb32 ? RARCH_GL_FORMAT32 : RARCH_GL_FORMAT16; gl->base_size = video->rgb32 ? sizeof(uint32_t) : sizeof(uint16_t); glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDisable(GL_DITHER); glClearColor(0, 0, 0, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertex_ptr); memcpy(gl->tex_coords, tex_coords, sizeof(tex_coords)); glTexCoordPointer(2, GL_FLOAT, 0, gl->tex_coords); glColorPointer(4, GL_FLOAT, 0, white_color); set_lut_texture_coords(tex_coords); gl->tex_w = RARCH_SCALE_BASE * video->input_scale; gl->tex_h = RARCH_SCALE_BASE * video->input_scale; #ifdef HAVE_OPENGL_TEXREF glGenBuffers(1, &gl->pbo); 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); #endif // Empty buffer that we use to clear out the texture with on res change. gl->empty_buf = calloc(gl->tex_w * gl->tex_h, gl->base_size); gl_init_textures(gl); for (unsigned i = 0; i < TEXTURES; i++) { gl->last_width[i] = gl->tex_w; gl->last_height[i] = gl->tex_h; } for (unsigned i = 0; i < TEXTURES; i++) { gl->prev_info[i].tex = gl->texture[(gl->tex_index - (i + 1)) & TEXTURES_MASK]; gl->prev_info[i].input_size[0] = gl->tex_w; gl->prev_info[i].tex_size[0] = gl->tex_w; gl->prev_info[i].input_size[1] = gl->tex_h; gl->prev_info[i].tex_size[1] = gl->tex_h; memcpy(gl->prev_info[i].coord, tex_coords, sizeof(tex_coords)); } 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(); free(gl); return NULL; } return gl; }
static bool gl_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, const char *msg) { gl_t *gl = (gl_t*)data; gl_shader_use(1); gl->frame_count++; glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]); #ifdef HAVE_FBO // Render to texture in first pass. if (gl->fbo_inited) { // Recompute FBO geometry. // When width/height changes or window sizes change, we have to recalcuate geometry of our FBO. gl_compute_fbo_geometry(gl, width, height, gl->vp_out_width, gl->vp_out_height); gl_start_frame_fbo(gl); } #endif if (gl->should_resize) { gl->should_resize = false; gfx_ctx_set_resize(gl->win_width, gl->win_height); // On resize, we might have to recreate our FBOs due to "Viewport" scale, and set a new viewport. gl_update_resize(gl); } if (frame) // Can be NULL for frame dupe / NULL render. { gl_update_input_size(gl, width, height, pitch); gl_copy_frame(gl, frame, width, height, pitch); } struct gl_tex_info tex_info = {0}; tex_info.tex = gl->texture[gl->tex_index]; tex_info.input_size[0] = width; tex_info.input_size[1] = height; tex_info.tex_size[0] = gl->tex_w; tex_info.tex_size[1] = gl->tex_h; memcpy(tex_info.coord, gl->tex_coords, sizeof(gl->tex_coords)); glClear(GL_COLOR_BUFFER_BIT); gl_shader_set_params(width, height, gl->tex_w, gl->tex_h, gl->vp_width, gl->vp_height, gl->frame_count, &tex_info, gl->prev_info, NULL, 0); glDrawArrays(GL_QUADS, 0, 4); #ifdef HAVE_FBO if (gl->fbo_inited) gl_frame_fbo(gl, &tex_info); #endif gl_next_texture_index(gl, &tex_info); if (msg) { gl_render_msg(gl, msg); gl_render_msg_post(gl); } #ifndef RARCH_CONSOLE gfx_ctx_update_window_title(false); #endif #ifdef RARCH_CONSOLE if (!gl->block_swap) #endif gfx_ctx_swap_buffers(); #ifdef HAVE_CG_MENU if (gl->menu_render) gl_render_menu(gl); #endif return true; }
static void gl_frame_fbo(gl_t *gl, const struct gl_tex_info *tex_info) { GLfloat fbo_tex_coords[8] = {0.0f}; // Render the rest of our passes. glTexCoordPointer(2, GL_FLOAT, 0, fbo_tex_coords); // It's kinda handy ... :) const struct gl_fbo_rect *prev_rect; const struct gl_fbo_rect *rect; struct gl_tex_info *fbo_info; struct gl_tex_info fbo_tex_info[MAX_SHADERS]; unsigned fbo_tex_info_cnt = 0; // Calculate viewports, texture coordinates etc, and render all passes from FBOs, to another FBO. for (int i = 1; i < gl->fbo_pass; i++) { prev_rect = &gl->fbo_rect[i - 1]; rect = &gl->fbo_rect[i]; fbo_info = &fbo_tex_info[i - 1]; GLfloat xamt = (GLfloat)prev_rect->img_width / prev_rect->width; GLfloat yamt = (GLfloat)prev_rect->img_height / prev_rect->height; set_texture_coords(fbo_tex_coords, xamt, yamt); fbo_info->tex = gl->fbo_texture[i - 1]; fbo_info->input_size[0] = prev_rect->img_width; fbo_info->input_size[1] = prev_rect->img_height; fbo_info->tex_size[0] = prev_rect->width; fbo_info->tex_size[1] = prev_rect->height; memcpy(fbo_info->coord, fbo_tex_coords, sizeof(fbo_tex_coords)); pglBindFramebuffer(GL_FRAMEBUFFER, gl->fbo[i]); gl_shader_use(i + 1); glBindTexture(GL_TEXTURE_2D, gl->fbo_texture[i - 1]); glClear(GL_COLOR_BUFFER_BIT); // Render to FBO with certain size. gl_set_viewport(gl, rect->img_width, rect->img_height, true, false); gl_shader_set_params(prev_rect->img_width, prev_rect->img_height, prev_rect->width, prev_rect->height, gl->vp_width, gl->vp_height, gl->frame_count, tex_info, gl->prev_info, fbo_tex_info, fbo_tex_info_cnt); glDrawArrays(GL_QUADS, 0, 4); fbo_tex_info_cnt++; } // Render our last FBO texture directly to screen. prev_rect = &gl->fbo_rect[gl->fbo_pass - 1]; GLfloat xamt = (GLfloat)prev_rect->img_width / prev_rect->width; GLfloat yamt = (GLfloat)prev_rect->img_height / prev_rect->height; set_texture_coords(fbo_tex_coords, xamt, yamt); // Render our FBO texture to back buffer. pglBindFramebuffer(GL_FRAMEBUFFER, 0); gl_shader_use(gl->fbo_pass + 1); glBindTexture(GL_TEXTURE_2D, gl->fbo_texture[gl->fbo_pass - 1]); glClear(GL_COLOR_BUFFER_BIT); gl->render_to_tex = false; gl_set_viewport(gl, gl->win_width, gl->win_height, false, true); gl_shader_set_params(prev_rect->img_width, prev_rect->img_height, prev_rect->width, prev_rect->height, gl->vp_width, gl->vp_height, gl->frame_count, tex_info, gl->prev_info, fbo_tex_info, fbo_tex_info_cnt); glVertexPointer(2, GL_FLOAT, 0, vertex_ptr); glDrawArrays(GL_QUADS, 0, 4); glTexCoordPointer(2, GL_FLOAT, 0, gl->tex_coords); }
static void *gl_init(const video_info_t *video, const input_driver_t **input, void **input_data) { #ifdef _WIN32 gfx_set_dwm(); #endif if (!sdlwrap_init()) return NULL; const SDL_VideoInfo *video_info = SDL_GetVideoInfo(); rarch_assert(video_info); unsigned full_x = video_info->current_w; unsigned full_y = video_info->current_h; RARCH_LOG("Detecting desktop resolution %ux%u.\n", full_x, full_y); sdlwrap_set_swap_interval(video->vsync ? 1 : 0, false); unsigned win_width = video->width; unsigned win_height = video->height; if (video->fullscreen && (win_width == 0) && (win_height == 0)) { win_width = full_x; win_height = full_y; } if (!sdlwrap_set_video_mode(win_width, win_height, g_settings.video.force_16bit ? 15 : 0, video->fullscreen)) return NULL; gfx_window_title_reset(); char buf[128]; if (gfx_window_title(buf, sizeof(buf))) sdlwrap_wm_set_caption(buf); // Remove that ugly mouse :D SDL_ShowCursor(SDL_DISABLE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #if (defined(HAVE_XML) || defined(HAVE_CG)) && defined(_WIN32) // Win32 GL lib doesn't have some functions needed for XML shaders. // Need to load dynamically :( if (!load_gl_proc()) { sdlwrap_destroy(); return NULL; } #endif gl_t *gl = (gl_t*)calloc(1, sizeof(gl_t)); if (!gl) { sdlwrap_destroy(); return NULL; } gl->vsync = video->vsync; gl->fullscreen = video->fullscreen; gl->full_x = full_x; gl->full_y = full_y; gl->win_width = win_width; gl->win_height = win_height; RARCH_LOG("GL: Using resolution %ux%u\n", gl->win_width, gl->win_height); if (!gl_shader_init()) { RARCH_ERR("Shader init failed.\n"); sdlwrap_destroy(); free(gl); return NULL; } RARCH_LOG("GL: Loaded %u program(s).\n", gl_shader_num()); #ifdef HAVE_FBO // Set up render to texture. gl_init_fbo(gl, RARCH_SCALE_BASE * video->input_scale, RARCH_SCALE_BASE * video->input_scale); #endif gl->keep_aspect = video->force_aspect; // Apparently need to set viewport for passes when we aren't using FBOs. gl_shader_use(0); set_viewport(gl, gl->win_width, gl->win_height, false, true); gl_shader_use(1); set_viewport(gl, gl->win_width, gl->win_height, false, true); bool force_smooth; if (gl_shader_filter_type(1, &force_smooth)) gl->tex_filter = force_smooth ? GL_LINEAR : GL_NEAREST; else gl->tex_filter = video->smooth ? GL_LINEAR : GL_NEAREST; gl->texture_type = GL_BGRA; gl->texture_fmt = video->rgb32 ? GL_UNSIGNED_INT_8_8_8_8_REV : GL_UNSIGNED_SHORT_1_5_5_5_REV; gl->base_size = video->rgb32 ? sizeof(uint32_t) : sizeof(uint16_t); glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDisable(GL_DITHER); glClearColor(0, 0, 0, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glGenTextures(TEXTURES, gl->texture); for (unsigned i = 0; i < TEXTURES; i++) { glBindTexture(GL_TEXTURE_2D, gl->texture[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl->tex_filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl->tex_filter); } glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertexes_flipped); memcpy(gl->tex_coords, tex_coords, sizeof(tex_coords)); glTexCoordPointer(2, GL_FLOAT, 0, gl->tex_coords); glColorPointer(4, GL_FLOAT, 0, white_color); set_lut_texture_coords(tex_coords); gl->tex_w = RARCH_SCALE_BASE * video->input_scale; gl->tex_h = RARCH_SCALE_BASE * video->input_scale; // Empty buffer that we use to clear out the texture with on res change. gl->empty_buf = calloc(gl->tex_w * gl->tex_h, gl->base_size); for (unsigned i = 0; i < TEXTURES; i++) { glBindTexture(GL_TEXTURE_2D, gl->texture[i]); glPixelStorei(GL_UNPACK_ROW_LENGTH, gl->tex_w); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gl->tex_w, gl->tex_h, 0, gl->texture_type, gl->texture_fmt, gl->empty_buf ? gl->empty_buf : NULL); } glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]); for (unsigned i = 0; i < TEXTURES; i++) { gl->last_width[i] = gl->tex_w; gl->last_height[i] = gl->tex_h; } for (unsigned i = 0; i < TEXTURES; i++) { gl->prev_info[i].tex = gl->texture[(gl->tex_index - (i + 1)) & TEXTURES_MASK]; gl->prev_info[i].input_size[0] = gl->tex_w; gl->prev_info[i].tex_size[0] = gl->tex_w; gl->prev_info[i].input_size[1] = gl->tex_h; gl->prev_info[i].tex_size[1] = gl->tex_h; memcpy(gl->prev_info[i].coord, tex_coords, sizeof(tex_coords)); } // Hook up SDL input driver to get SDL_QUIT events and RESIZE. sdl_input_t *sdl_input = (sdl_input_t*)input_sdl.init(); if (sdl_input) { *input = &input_sdl; *input_data = sdl_input; } else *input = NULL; gl_init_font(gl, g_settings.video.font_path, g_settings.video.font_size); if (!gl_check_error()) { sdlwrap_destroy(); free(gl); return NULL; } return gl; }