static void _upload_memory (GstGLMemory * gl_mem, GstMapInfo * info, gsize maxsize) { GstGLContext *context = gl_mem->mem.context; const GstGLFuncs *gl; GLenum gl_format, gl_type, gl_target; gpointer data; gsize plane_start; if ((gl_mem->transfer_state & GST_GL_MEMORY_TRANSFER_NEED_UPLOAD) == 0) return; gl = context->gl_vtable; gl_type = GL_UNSIGNED_BYTE; if (gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16) gl_type = GL_UNSIGNED_SHORT_5_6_5; gl_format = gst_gl_format_from_gl_texture_type (gl_mem->tex_type); gl_target = gl_mem->tex_target; if (USING_OPENGL (context) || USING_GLES3 (context) || USING_OPENGL3 (context)) { gl->PixelStorei (GL_UNPACK_ROW_LENGTH, gl_mem->unpack_length); } else if (USING_GLES2 (context)) { gl->PixelStorei (GL_UNPACK_ALIGNMENT, gl_mem->unpack_length); } GST_LOG ("upload for texture id:%u, with pbo %u %ux%u", gl_mem->tex_id, gl_mem->mem.id, gl_mem->tex_width, GL_MEM_HEIGHT (gl_mem)); /* find the start of the plane data including padding */ plane_start = _find_plane_frame_start (gl_mem); if (gl_mem->mem.id && CONTEXT_SUPPORTS_PBO_UPLOAD (context)) { gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, gl_mem->mem.id); data = (void *) plane_start; } else { data = (gpointer) ((gintptr) plane_start + (gintptr) gl_mem->mem.data); } gl->BindTexture (gl_target, gl_mem->tex_id); gl->TexSubImage2D (gl_target, 0, 0, 0, gl_mem->tex_width, GL_MEM_HEIGHT (gl_mem), gl_format, gl_type, data); if (gl_mem->mem.id && CONTEXT_SUPPORTS_PBO_UPLOAD (context)) gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); /* Reset to default values */ if (USING_OPENGL (context) || USING_GLES3 (context)) { gl->PixelStorei (GL_UNPACK_ROW_LENGTH, 0); } else if (USING_GLES2 (context)) { gl->PixelStorei (GL_UNPACK_ALIGNMENT, 4); } gl->BindTexture (gl_target, 0); gl_mem->transfer_state &= ~GST_GL_MEMORY_TRANSFER_NEED_UPLOAD; }
guint gst_gl_sized_gl_format_from_gl_format_type (GstGLContext * context, guint format, guint type) { gboolean ext_texture_rg = gst_gl_context_check_feature (context, "GL_EXT_texture_rg"); switch (format) { case GL_RGBA: switch (type) { case GL_UNSIGNED_BYTE: return USING_GLES2 (context) && !USING_GLES3 (context) ? GL_RGBA : GL_RGBA8; break; } break; case GL_RGB: switch (type) { case GL_UNSIGNED_BYTE: return GL_RGB8; break; case GL_UNSIGNED_SHORT_5_6_5: return GL_RGB; break; } break; case GL_RG: switch (type) { case GL_UNSIGNED_BYTE: if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg) return GL_RG; return GL_RG8; break; } break; case GL_RED: switch (type) { case GL_UNSIGNED_BYTE: if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg) return GL_RED; return GL_R8; break; } break; case GL_LUMINANCE: return GL_LUMINANCE; break; case GL_LUMINANCE_ALPHA: return GL_LUMINANCE_ALPHA; break; case GL_ALPHA: return GL_ALPHA; break; default: break; } g_assert_not_reached (); return 0; }
static void _upload_pbo_memory (GstGLMemoryPBO * gl_mem, GstMapInfo * info, GstGLBuffer * pbo, GstMapInfo * pbo_info) { GstGLContext *context = gl_mem->mem.mem.context; const GstGLFuncs *gl; guint gl_format, gl_type, gl_target; guint pbo_id; gsize plane_start; if (!GST_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD)) return; g_return_if_fail (CONTEXT_SUPPORTS_PBO_UPLOAD (context)); gl = context->gl_vtable; pbo_id = *(guint *) pbo_info->data; gl_type = GL_UNSIGNED_BYTE; if (gl_mem->mem.tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16) gl_type = GL_UNSIGNED_SHORT_5_6_5; gl_format = gst_gl_format_from_gl_texture_type (gl_mem->mem.tex_type); gl_target = gst_gl_texture_target_to_gl (gl_mem->mem.tex_target); if (USING_OPENGL (context) || USING_GLES3 (context) || USING_OPENGL3 (context)) { gl->PixelStorei (GL_UNPACK_ROW_LENGTH, gl_mem->mem.unpack_length); } else if (USING_GLES2 (context)) { gl->PixelStorei (GL_UNPACK_ALIGNMENT, gl_mem->mem.unpack_length); } GST_CAT_LOG (GST_CAT_GL_MEMORY, "upload for texture id:%u, with pbo %u %ux%u", gl_mem->mem.tex_id, pbo_id, gl_mem->mem.tex_width, GL_MEM_HEIGHT (gl_mem)); /* find the start of the plane data including padding */ plane_start = gst_gl_get_plane_start (&gl_mem->mem.info, &gl_mem->mem.valign, gl_mem->mem.plane) + GST_MEMORY_CAST (gl_mem)->offset; gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo_id); gl->BindTexture (gl_target, gl_mem->mem.tex_id); gl->TexSubImage2D (gl_target, 0, 0, 0, gl_mem->mem.tex_width, GL_MEM_HEIGHT (gl_mem), gl_format, gl_type, (void *) plane_start); gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); gl->BindTexture (gl_target, 0); /* Reset to default values */ if (USING_OPENGL (context) || USING_GLES3 (context)) { gl->PixelStorei (GL_UNPACK_ROW_LENGTH, 0); } else if (USING_GLES2 (context)) { gl->PixelStorei (GL_UNPACK_ALIGNMENT, 4); } }
static gboolean _init_download (GstGLDownload * download) { GstVideoFormat v_format; guint out_width, out_height; GstVideoInfo in_info; v_format = GST_VIDEO_INFO_FORMAT (&download->info); out_width = GST_VIDEO_INFO_WIDTH (&download->info); out_height = GST_VIDEO_INFO_HEIGHT (&download->info); if (download->initted) return TRUE; GST_TRACE ("initializing texture download for format %s", gst_video_format_to_string (v_format)); if (USING_GLES2 (download->context) && !USING_GLES3 (download->context)) { /* GL_RGBA is the only officially supported texture format in GLES2 */ if (v_format == GST_VIDEO_FORMAT_RGB || v_format == GST_VIDEO_FORMAT_BGR) { gst_gl_context_set_error (download->context, "Cannot download RGB " "textures in GLES2"); return FALSE; } } gst_video_info_set_format (&in_info, GST_VIDEO_FORMAT_RGBA, out_width, out_height); gst_gl_color_convert_set_format (download->convert, &in_info, &download->info); return TRUE; }
static void _upload_memory (GstGLContext * context, GstGLMemory * gl_mem) { const GstGLFuncs *gl; GLenum gl_format, gl_type; if (!GST_GL_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD)) { return; } gl = context->gl_vtable; gl_type = GL_UNSIGNED_BYTE; if (gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16) gl_type = GL_UNSIGNED_SHORT_5_6_5; gl_format = _gst_gl_format_from_gl_texture_type (gl_mem->tex_type); if (USING_OPENGL (context) || USING_GLES3 (context)) { gl->PixelStorei (GL_UNPACK_ROW_LENGTH, gl_mem->unpack_length); } else if (USING_GLES2 (context)) { gl->PixelStorei (GL_UNPACK_ALIGNMENT, gl_mem->unpack_length); } GST_CAT_LOG (GST_CAT_GL_MEMORY, "upload for texture id:%u, %ux%u", gl_mem->tex_id, gl_mem->tex_width, GL_MEM_HEIGHT (gl_mem)); gl->BindTexture (GL_TEXTURE_2D, gl_mem->tex_id); gl->TexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, gl_mem->tex_width, GL_MEM_HEIGHT (gl_mem), gl_format, gl_type, gl_mem->data); /* Reset to default values */ if (USING_OPENGL (context) || USING_GLES3 (context)) { gl->PixelStorei (GL_UNPACK_ROW_LENGTH, 0); } else if (USING_GLES2 (context)) { gl->PixelStorei (GL_UNPACK_ALIGNMENT, 4); } gl->BindTexture (GL_TEXTURE_2D, 0); GST_GL_MEMORY_FLAG_UNSET (gl_mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD); }
static inline void _calculate_unpack_length (GstGLMemory * gl_mem) { guint n_gl_bytes; gl_mem->tex_scaling[0] = 1.0f; gl_mem->tex_scaling[1] = 1.0f; gl_mem->unpack_length = 1; gl_mem->tex_width = GL_MEM_WIDTH (gl_mem); n_gl_bytes = _gl_texture_type_n_bytes (gl_mem->tex_type); if (n_gl_bytes == 0) { GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Unsupported texture type %d", gl_mem->tex_type); return; } if (USING_OPENGL (gl_mem->context) || USING_GLES3 (gl_mem->context)) { gl_mem->unpack_length = GL_MEM_STRIDE (gl_mem) / n_gl_bytes; } else if (USING_GLES2 (gl_mem->context)) { guint j = 8; while (j >= n_gl_bytes) { /* GST_ROUND_UP_j(GL_MEM_WIDTH (gl_mem) * n_gl_bytes) */ guint round_up_j = ((GL_MEM_WIDTH (gl_mem) * n_gl_bytes) + j - 1) & ~(j - 1); if (round_up_j == GL_MEM_STRIDE (gl_mem)) { GST_CAT_LOG (GST_CAT_GL_MEMORY, "Found alignment of %u based on width " "(with plane width:%u, plane stride:%u and pixel stride:%u. " "RU%u(%u*%u) = %u)", j, GL_MEM_WIDTH (gl_mem), GL_MEM_STRIDE (gl_mem), n_gl_bytes, j, GL_MEM_WIDTH (gl_mem), n_gl_bytes, round_up_j); gl_mem->unpack_length = j; break; } j >>= 1; } if (j < n_gl_bytes) { /* Failed to find a suitable alignment, try based on plane_stride and * scale in the shader. Useful for alignments that are greater than 8. */ j = 8; while (j >= n_gl_bytes) { /* GST_ROUND_UP_j((GL_MEM_STRIDE (gl_mem)) */ guint round_up_j = ((GL_MEM_STRIDE (gl_mem)) + j - 1) & ~(j - 1); if (round_up_j == (GL_MEM_STRIDE (gl_mem))) { GST_CAT_LOG (GST_CAT_GL_MEMORY, "Found alignment of %u based on " "stride (with plane stride:%u and pixel stride:%u. " "RU%u(%u) = %u)", j, GL_MEM_STRIDE (gl_mem), n_gl_bytes, j, GL_MEM_STRIDE (gl_mem), round_up_j); gl_mem->unpack_length = j; gl_mem->tex_scaling[0] = (gfloat) (GL_MEM_WIDTH (gl_mem) * n_gl_bytes) / (gfloat) GL_MEM_STRIDE (gl_mem); gl_mem->tex_width = GL_MEM_STRIDE (gl_mem) / n_gl_bytes; break; } j >>= 1; } if (j < n_gl_bytes) { GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Failed to find matching alignment. Image may " "look corrupted. plane width:%u, plane stride:%u and pixel " "stride:%u", GL_MEM_WIDTH (gl_mem), GL_MEM_STRIDE (gl_mem), n_gl_bytes); } }