From 28eaf11cf3b220871b97d9ba40d5058a84bcba09 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 6 Oct 2011 20:46:01 +0200 Subject: vo_gl: implement screenshots --- libvo/gl_common.c | 19 ++++++++++++++++++ libvo/gl_common.h | 2 ++ libvo/vo_gl.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/libvo/gl_common.c b/libvo/gl_common.c index bbcbeb2f3b..f433f5642d 100644 --- a/libvo/gl_common.c +++ b/libvo/gl_common.c @@ -71,6 +71,7 @@ void glAdjustAlignment(GL *gl, int stride) else gl_alignment = 1; gl->PixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment); + gl->PixelStorei(GL_PACK_ALIGNMENT, gl_alignment); } struct gl_name_map_struct { @@ -634,6 +635,24 @@ void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type, gl->TexSubImage2D(target, 0, x, y, w, y_max - y, format, type, data); } +/** + * \brief download a texture, handling things like stride and slices + * \param target texture target, usually GL_TEXTURE_2D + * \param format OpenGL format of data + * \param type OpenGL type of data + * \param dataptr destination memory for download + * \param stride data stride (must be positive) + * \ingroup gltexture + */ +void glDownloadTex(GL *gl, GLenum target, GLenum format, GLenum type, + void *dataptr, int stride) +{ + // this is not always correct, but should work for MPlayer + glAdjustAlignment(gl, stride); + gl->PixelStorei(GL_PACK_ROW_LENGTH, stride / glFmt2bpp(format, type)); + gl->GetTexImage(target, 0, format, type, dataptr); +} + /** * \brief Setup ATI version of register combiners for YUV to RGB conversion. * \param csp_params parameters used for colorspace conversion diff --git a/libvo/gl_common.h b/libvo/gl_common.h index a56248403a..d1d034b99a 100644 --- a/libvo/gl_common.h +++ b/libvo/gl_common.h @@ -256,6 +256,8 @@ int glCreatePPMTex(GL *gl, GLenum target, GLenum fmt, GLint filter, void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type, const void *dataptr, int stride, int x, int y, int w, int h, int slice); +void glDownloadTex(GL *gl, GLenum target, GLenum format, GLenum type, + void *dataptr, int stride); void glDrawTex(GL *gl, GLfloat x, GLfloat y, GLfloat w, GLfloat h, GLfloat tx, GLfloat ty, GLfloat tw, GLfloat th, int sx, int sy, int rect_tex, int is_yv12, int flip); diff --git a/libvo/vo_gl.c b/libvo/vo_gl.c index 5f06cf7148..e99ff4432f 100644 --- a/libvo/vo_gl.c +++ b/libvo/vo_gl.c @@ -1134,6 +1134,57 @@ skip_upload: return VO_TRUE; } +static mp_image_t *get_screenshot(struct vo *vo) +{ + struct gl_priv *p = vo->priv; + GL *gl = p->gl; + + mp_image_t *image = alloc_mpi(p->texture_width, p->texture_height, + p->image_format); + + glDownloadTex(gl, p->target, p->gl_format, p->gl_type, image->planes[0], + image->stride[0]); + + if (p->is_yuv) { + gl->ActiveTexture(GL_TEXTURE1); + glDownloadTex(gl, p->target, p->gl_format, p->gl_type, image->planes[1], + image->stride[1]); + gl->ActiveTexture(GL_TEXTURE2); + glDownloadTex(gl, p->target, p->gl_format, p->gl_type, image->planes[2], + image->stride[2]); + gl->ActiveTexture(GL_TEXTURE0); + } + + image->width = p->image_width; + image->height = p->image_height; + + image->w = p->image_d_width; + image->h = p->image_d_height; + + return image; +} + +static mp_image_t *get_window_screenshot(struct vo *vo) +{ + struct gl_priv *p = vo->priv; + GL *gl = p->gl; + + GLint vp[4]; //x, y, w, h + gl->GetIntegerv(GL_VIEWPORT, vp); + mp_image_t *image = alloc_mpi(vp[2], vp[3], IMGFMT_RGB24); + gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + gl->PixelStorei(GL_PACK_ALIGNMENT, 0); + gl->PixelStorei(GL_PACK_ROW_LENGTH, 0); + gl->ReadBuffer(GL_FRONT); + //flip image while reading + for (int y = 0; y < vp[3]; y++) { + gl->ReadPixels(vp[0], vp[1] + vp[3] - y - 1, vp[2], 1, + GL_RGB, GL_UNSIGNED_BYTE, + image->planes[0] + y * image->stride[0]); + } + return image; +} + static int query_format(struct vo *vo, uint32_t format) { struct gl_priv *p = vo->priv; @@ -1460,6 +1511,14 @@ static int control(struct vo *vo, uint32_t request, void *data) do_render_osd(vo, 2); flip_page(vo); return VO_TRUE; + case VOCTRL_SCREENSHOT: { + struct voctrl_screenshot_args *args = data; + if (args->full_window) + args->out_image = get_window_screenshot(vo); + else + args->out_image = get_screenshot(vo); + return true; + } } return VO_NOTIMPL; } -- cgit v1.2.3