static bool gl1_overlay_load(void *data, const void *image_data, unsigned num_images) { unsigned i, j; gl1_t *gl = (gl1_t*)data; const struct texture_image *images = (const struct texture_image*)image_data; if (!gl) return false; gl1_context_bind_hw_render(gl, false); gl1_free_overlay(gl); gl->overlay_tex = (GLuint*) calloc(num_images, sizeof(*gl->overlay_tex)); if (!gl->overlay_tex) { gl1_context_bind_hw_render(gl, true); return false; } gl->overlay_vertex_coord = (GLfloat*) calloc(2 * 4 * num_images, sizeof(GLfloat)); gl->overlay_tex_coord = (GLfloat*) calloc(2 * 4 * num_images, sizeof(GLfloat)); gl->overlay_color_coord = (GLfloat*) calloc(4 * 4 * num_images, sizeof(GLfloat)); if ( !gl->overlay_vertex_coord || !gl->overlay_tex_coord || !gl->overlay_color_coord) return false; gl->overlays = num_images; glGenTextures(num_images, gl->overlay_tex); for (i = 0; i < num_images; i++) { unsigned alignment = video_pixel_get_alignment(images[i].width * sizeof(uint32_t)); gl1_load_texture_data(gl->overlay_tex[i], RARCH_WRAP_EDGE, TEXTURE_FILTER_LINEAR, alignment, images[i].width, images[i].height, images[i].pixels, sizeof(uint32_t)); /* Default. Stretch to whole screen. */ gl1_overlay_tex_geom(gl, i, 0, 0, 1, 1); gl1_overlay_vertex_geom(gl, i, 0, 0, 1, 1); for (j = 0; j < 16; j++) gl->overlay_color_coord[16 * i + j] = 1.0f; } gl1_context_bind_hw_render(gl, true); return true; }
static void gl1_renderchain_copy_frame( void *data, void *chain_data, video_frame_info_t *video_info, const void *frame, unsigned width, unsigned height, unsigned pitch) { gl_t *gl = (gl_t*)data; const GLvoid *data_buf = frame; glPixelStorei(GL_UNPACK_ALIGNMENT, video_pixel_get_alignment(pitch)); if (gl->base_size == 2 && !gl->have_es2_compat) { /* Convert to 32-bit textures on desktop GL. * * It is *much* faster (order of magnitude on my setup) * to use a custom SIMD-optimized conversion routine * than letting GL do it. */ video_frame_convert_rgb16_to_rgb32( &gl->scaler, gl->conv_buffer, frame, width, height, pitch); data_buf = gl->conv_buffer; } else glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / gl->base_size); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, gl->texture_type, gl->texture_fmt, data_buf); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); }
static void gl2_renderchain_copy_frame( void *data, void *chain_data, video_frame_info_t *video_info, const void *frame, unsigned width, unsigned height, unsigned pitch) { gl_t *gl = (gl_t*)data; gl2_renderchain_t *chain = (gl2_renderchain_t*)chain_data; (void)chain; #if defined(HAVE_PSGL) { unsigned h; size_t buffer_addr = gl->tex_w * gl->tex_h * gl->tex_index * gl->base_size; size_t buffer_stride = gl->tex_w * gl->base_size; const uint8_t *frame_copy = frame; size_t frame_copy_size = width * gl->base_size; uint8_t *buffer = (uint8_t*)glMapBuffer( GL_TEXTURE_REFERENCE_BUFFER_SCE, GL_READ_WRITE) + buffer_addr; for (h = 0; h < height; h++, buffer += buffer_stride, frame_copy += pitch) memcpy(buffer, frame_copy, frame_copy_size); glUnmapBuffer(GL_TEXTURE_REFERENCE_BUFFER_SCE); } #elif defined(HAVE_OPENGLES) #if defined(HAVE_EGL) if (chain->egl_images) { gfx_ctx_image_t img_info; bool new_egl = false; EGLImageKHR img = 0; img_info.frame = frame; img_info.width = width; img_info.height = height; img_info.pitch = pitch; img_info.index = gl->tex_index; img_info.rgb32 = (gl->base_size == 4); img_info.handle = &img; new_egl = video_context_driver_write_to_image_buffer(&img_info); if (img == EGL_NO_IMAGE_KHR) { RARCH_ERR("[GL]: Failed to create EGL image.\n"); return; } if (new_egl) glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)img); } else #endif { glPixelStorei(GL_UNPACK_ALIGNMENT, video_pixel_get_alignment(width * gl->base_size)); /* Fallback for GLES devices without GL_BGRA_EXT. */ if (gl->base_size == 4 && video_info->use_rgba) { video_frame_convert_argb8888_to_abgr8888( &gl->scaler, gl->conv_buffer, frame, width, height, pitch); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, gl->texture_type, gl->texture_fmt, gl->conv_buffer); } else if (gl->support_unpack_row_length) { 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); } else { /* No GL_UNPACK_ROW_LENGTH. */ const GLvoid *data_buf = frame; unsigned pitch_width = pitch / gl->base_size; if (width != pitch_width) { /* Slow path - conv_buffer is preallocated * just in case we hit this path. */ unsigned h; const unsigned line_bytes = width * gl->base_size; uint8_t *dst = (uint8_t*)gl->conv_buffer; const uint8_t *src = (const uint8_t*)frame; for (h = 0; h < height; h++, src += pitch, dst += line_bytes) memcpy(dst, src, line_bytes); data_buf = gl->conv_buffer; } glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, gl->texture_type, gl->texture_fmt, data_buf); } } #else { const GLvoid *data_buf = frame; glPixelStorei(GL_UNPACK_ALIGNMENT, video_pixel_get_alignment(pitch)); if (gl->base_size == 2 && !gl->have_es2_compat) { /* Convert to 32-bit textures on desktop GL. * * It is *much* faster (order of magnitude on my setup) * to use a custom SIMD-optimized conversion routine * than letting GL do it. */ video_frame_convert_rgb16_to_rgb32( &gl->scaler, gl->conv_buffer, frame, width, height, pitch); data_buf = gl->conv_buffer; } else glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / gl->base_size); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, gl->texture_type, gl->texture_fmt, data_buf); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } #endif }