/* Draw one video frame onto EGL surface. * @param vt vidtex instance. * @param video_frame MMAL opaque buffer handle for decoded video frame. Can't be NULL. */ static void vidtex_draw(VIDTEX_T *vt, void *video_frame) { EGLImageKHR image; VIDTEX_IMAGE_SLOT_T *slot; static uint32_t frame_num = 0; vcos_assert(video_frame); glClearColor(0, 0, 0, 0); glClearDepthf(1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glBindTexture(GL_TEXTURE_EXTERNAL_OES, vt->texture); VIDTEX_CHECK_GL(vt); /* Lookup or create EGL image corresponding to supplied buffer handle. * N.B. Slot array is filled in sequentially, with the images all destroyed together on * vidtex termination; it never has holes. */ image = EGL_NO_IMAGE_KHR; for (slot = vt->slots; slot < vt->slots + vcos_countof(vt->slots); slot++) { if (slot->video_frame == video_frame) { vcos_assert(slot->image); image = slot->image; break; } if (slot->video_frame == NULL) { EGLenum target; vcos_assert(slot->image == NULL); if (vt->opts & VIDTEX_OPT_Y_TEXTURE) target = EGL_IMAGE_BRCM_MULTIMEDIA_Y; else if (vt->opts & VIDTEX_OPT_U_TEXTURE) target = EGL_IMAGE_BRCM_MULTIMEDIA_U; else if (vt->opts & VIDTEX_OPT_V_TEXTURE) target = EGL_IMAGE_BRCM_MULTIMEDIA_V; else target = EGL_IMAGE_BRCM_MULTIMEDIA; image = eglCreateImageKHR(vt->display, EGL_NO_CONTEXT, target, (EGLClientBuffer)video_frame, NULL); if (image == EGL_NO_IMAGE_KHR) { vcos_log_error("EGL image conversion error"); } else { vcos_log_trace("Created EGL image %p for buf %p", image, video_frame); slot->video_frame = video_frame; slot->image = image; } VIDTEX_CHECK_GL(vt); break; } } if (slot == vt->slots + vcos_countof(vt->slots)) { vcos_log_error("Exceeded configured max number of EGL images"); } /* Draw the EGL image */ if (image != EGL_NO_IMAGE_KHR) { /* Assume 30fps */ int frames_per_rev = 30 * 15; GLfloat angle = (frame_num * 360) / (GLfloat) frames_per_rev; frame_num = (frame_num + 1) % frames_per_rev; glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image); VIDTEX_CHECK_GL(vt); glRotatef(angle, 0.0, 0.0, 1.0); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vt_vertices); glDisableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, vt_tex_coords); glDrawArrays(GL_TRIANGLES, 0, vcos_countof(vt_tex_coords) / 2); eglSwapBuffers(vt->display, vt->surface); if (vt->opts & VIDTEX_OPT_IMG_PER_FRAME) { vidtex_destroy_images(vt); } vt->num_swaps++; } VIDTEX_CHECK_GL(vt); }
int glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, PixmapPtr pixmap, unsigned int tex, Bool want_name, CARD16 *stride, CARD32 *size) { #ifdef GLAMOR_HAS_GBM ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); struct glamor_egl_screen_private *glamor_egl; EGLImageKHR image; struct gbm_bo *bo; int fd = -1; EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE }; glamor_egl = glamor_egl_get_screen_private(scrn); glamor_get_context(glamor_priv); image = dixLookupPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key); if (image == EGL_NO_IMAGE_KHR || image == NULL) { image = eglCreateImageKHR(glamor_egl->display, glamor_egl->context, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) (uintptr_t) tex, attribs); if (image == EGL_NO_IMAGE_KHR) goto failure; dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, image); glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); } bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0); if (!bo) goto failure; pixmap->devKind = gbm_bo_get_stride(bo); if (want_name) { if (glamor_egl->has_gem) glamor_get_name_from_bo(glamor_egl->fd, bo, &fd); } else { if (glamor_get_fd_from_bo(glamor_egl->fd, bo, &fd)) { *stride = pixmap->devKind; *size = pixmap->devKind * gbm_bo_get_height(bo); } } gbm_bo_destroy(bo); failure: glamor_put_context(glamor_priv); return fd; #else return -1; #endif }
PixmapPtr glamor_egl_dri3_pixmap_from_fd(ScreenPtr screen, int fd, CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp) { #ifdef GLAMOR_HAS_GBM ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl; struct gbm_bo *bo; EGLImageKHR image; PixmapPtr pixmap; Bool ret = FALSE; EGLint attribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, EGL_DMA_BUF_PLANE0_FD_EXT, 0, EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, EGL_DMA_BUF_PLANE0_PITCH_EXT, 0, EGL_NONE }; glamor_egl = glamor_egl_get_screen_private(scrn); if (!glamor_egl->dri3_capable) return NULL; if (bpp != 32 || !(depth == 24 || depth == 32) || width == 0 || height == 0) return NULL; attribs[1] = width; attribs[3] = height; attribs[7] = fd; attribs[11] = stride; image = eglCreateImageKHR(glamor_egl->display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attribs); if (image == EGL_NO_IMAGE_KHR) return NULL; /* EGL_EXT_image_dma_buf_import can impose restrictions on the * usage of the image. Use gbm_bo to bypass the limitations. */ bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0); eglDestroyImageKHR(glamor_egl->display, image); if (!bo) return NULL; pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0); screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL); ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo); gbm_bo_destroy(bo); if (ret) return pixmap; else { screen->DestroyPixmap(pixmap); return NULL; } #else return NULL; #endif }
GstBuffer * gst_egl_image_allocator_alloc_eglimage (GstAllocator * allocator, GstEGLDisplay * display, EGLContext eglcontext, GstVideoFormat format, gint width, gint height) { GstEGLGLESImageData *data = NULL; GstBuffer *buffer; GstVideoInfo info; gint i; gint stride[3]; gsize offset[3]; GstMemory *mem[3] = { NULL, NULL, NULL }; guint n_mem; GstMemoryFlags flags = 0; memset (stride, 0, sizeof (stride)); memset (offset, 0, sizeof (offset)); if (!gst_egl_image_memory_is_mappable ()) flags |= GST_MEMORY_FLAG_NOT_MAPPABLE; /* See https://bugzilla.gnome.org/show_bug.cgi?id=695203 */ flags |= GST_MEMORY_FLAG_NO_SHARE; gst_video_info_set_format (&info, format, width, height); switch (format) { case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_BGR:{ gsize size; EGLImageKHR image; mem[0] = gst_egl_image_allocator_alloc (allocator, display, GST_VIDEO_GL_TEXTURE_TYPE_RGB, GST_VIDEO_INFO_WIDTH (&info), GST_VIDEO_INFO_HEIGHT (&info), &size); if (mem[0]) { stride[0] = size / GST_VIDEO_INFO_HEIGHT (&info); n_mem = 1; GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE); } else { data = g_slice_new0 (GstEGLGLESImageData); stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (&info) * 3); size = stride[0] * GST_VIDEO_INFO_HEIGHT (&info); glGenTextures (1, &data->texture); if (got_gl_error ("glGenTextures")) goto mem_error; glBindTexture (GL_TEXTURE_2D, data->texture); if (got_gl_error ("glBindTexture")) goto mem_error; /* Set 2D resizing params */ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* If these are not set the texture image unit will return * * (R, G, B, A) = black on glTexImage2D for non-POT width/height * * frames. For a deeper explanation take a look at the OpenGL ES * * documentation for glTexParameter */ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (got_gl_error ("glTexParameteri")) goto mem_error; glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, GST_VIDEO_INFO_WIDTH (&info), GST_VIDEO_INFO_HEIGHT (&info), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); if (got_gl_error ("glTexImage2D")) goto mem_error; image = eglCreateImageKHR (gst_egl_display_get (display), eglcontext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) (guintptr) data->texture, NULL); if (got_egl_error ("eglCreateImageKHR")) goto mem_error; mem[0] = gst_egl_image_allocator_wrap (allocator, display, image, GST_VIDEO_GL_TEXTURE_TYPE_RGB, flags, size, data, (GDestroyNotify) gst_egl_gles_image_data_free); n_mem = 1; } break; } case GST_VIDEO_FORMAT_RGB16:{ EGLImageKHR image; gsize size; mem[0] = gst_egl_image_allocator_alloc (allocator, display, GST_VIDEO_GL_TEXTURE_TYPE_RGB, GST_VIDEO_INFO_WIDTH (&info), GST_VIDEO_INFO_HEIGHT (&info), &size); if (mem[0]) { stride[0] = size / GST_VIDEO_INFO_HEIGHT (&info); n_mem = 1; GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE); } else { data = g_slice_new0 (GstEGLGLESImageData); stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (&info) * 2); size = stride[0] * GST_VIDEO_INFO_HEIGHT (&info); glGenTextures (1, &data->texture); if (got_gl_error ("glGenTextures")) goto mem_error; glBindTexture (GL_TEXTURE_2D, data->texture); if (got_gl_error ("glBindTexture")) goto mem_error; /* Set 2D resizing params */ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* If these are not set the texture image unit will return * * (R, G, B, A) = black on glTexImage2D for non-POT width/height * * frames. For a deeper explanation take a look at the OpenGL ES * * documentation for glTexParameter */ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (got_gl_error ("glTexParameteri")) goto mem_error; glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, GST_VIDEO_INFO_WIDTH (&info), GST_VIDEO_INFO_HEIGHT (&info), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); if (got_gl_error ("glTexImage2D")) goto mem_error; image = eglCreateImageKHR (gst_egl_display_get (display), eglcontext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) (guintptr) data->texture, NULL); if (got_egl_error ("eglCreateImageKHR")) goto mem_error; mem[0] = gst_egl_image_allocator_wrap (allocator, display, image, GST_VIDEO_GL_TEXTURE_TYPE_RGB, flags, size, data, (GDestroyNotify) gst_egl_gles_image_data_free); n_mem = 1; } break; } case GST_VIDEO_FORMAT_NV12: case GST_VIDEO_FORMAT_NV21:{ EGLImageKHR image; gsize size[2]; mem[0] = gst_egl_image_allocator_alloc (allocator, display, GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info, 0), GST_VIDEO_INFO_COMP_HEIGHT (&info, 0), &size[0]); mem[1] = gst_egl_image_allocator_alloc (allocator, display, GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA, GST_VIDEO_INFO_COMP_WIDTH (&info, 1), GST_VIDEO_INFO_COMP_HEIGHT (&info, 1), &size[1]); if (mem[0] && mem[1]) { stride[0] = size[0] / GST_VIDEO_INFO_HEIGHT (&info); offset[1] = size[0]; stride[1] = size[1] / GST_VIDEO_INFO_HEIGHT (&info); n_mem = 2; GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE); GST_MINI_OBJECT_FLAG_SET (mem[1], GST_MEMORY_FLAG_NO_SHARE); } else { if (mem[0]) gst_memory_unref (mem[0]); if (mem[1]) gst_memory_unref (mem[1]); mem[0] = mem[1] = NULL; stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 0)); stride[1] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 1) * 2); offset[1] = stride[0] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 0); size[0] = offset[1]; size[1] = stride[1] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 1); for (i = 0; i < 2; i++) { data = g_slice_new0 (GstEGLGLESImageData); glGenTextures (1, &data->texture); if (got_gl_error ("glGenTextures")) goto mem_error; glBindTexture (GL_TEXTURE_2D, data->texture); if (got_gl_error ("glBindTexture")) goto mem_error; /* Set 2D resizing params */ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* If these are not set the texture image unit will return * * (R, G, B, A) = black on glTexImage2D for non-POT width/height * * frames. For a deeper explanation take a look at the OpenGL ES * * documentation for glTexParameter */ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (got_gl_error ("glTexParameteri")) goto mem_error; if (i == 0) glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info, i), GST_VIDEO_INFO_COMP_HEIGHT (&info, i), 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); else glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, GST_VIDEO_INFO_COMP_WIDTH (&info, i), GST_VIDEO_INFO_COMP_HEIGHT (&info, i), 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); if (got_gl_error ("glTexImage2D")) goto mem_error; image = eglCreateImageKHR (gst_egl_display_get (display), eglcontext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) (guintptr) data->texture, NULL); if (got_egl_error ("eglCreateImageKHR")) goto mem_error; mem[i] = gst_egl_image_allocator_wrap (allocator, display, image, (i == 0 ? GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE : GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA), flags, size[i], data, (GDestroyNotify) gst_egl_gles_image_data_free); } n_mem = 2; } break; } case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_Y444: case GST_VIDEO_FORMAT_Y42B: case GST_VIDEO_FORMAT_Y41B:{ EGLImageKHR image; gsize size[3]; mem[0] = gst_egl_image_allocator_alloc (allocator, display, GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info, 0), GST_VIDEO_INFO_COMP_HEIGHT (&info, 0), &size[0]); mem[1] = gst_egl_image_allocator_alloc (allocator, display, GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info, 1), GST_VIDEO_INFO_COMP_HEIGHT (&info, 1), &size[1]); mem[2] = gst_egl_image_allocator_alloc (allocator, display, GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info, 2), GST_VIDEO_INFO_COMP_HEIGHT (&info, 2), &size[2]); if (mem[0] && mem[1] && mem[2]) { stride[0] = size[0] / GST_VIDEO_INFO_HEIGHT (&info); offset[1] = size[0]; stride[1] = size[1] / GST_VIDEO_INFO_HEIGHT (&info); offset[2] = size[1]; stride[2] = size[2] / GST_VIDEO_INFO_HEIGHT (&info); n_mem = 3; GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE); GST_MINI_OBJECT_FLAG_SET (mem[1], GST_MEMORY_FLAG_NO_SHARE); GST_MINI_OBJECT_FLAG_SET (mem[2], GST_MEMORY_FLAG_NO_SHARE); } else { if (mem[0]) gst_memory_unref (mem[0]); if (mem[1]) gst_memory_unref (mem[1]); if (mem[2]) gst_memory_unref (mem[2]); mem[0] = mem[1] = mem[2] = NULL; stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 0)); stride[1] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 1)); stride[2] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 2)); size[0] = stride[0] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 0); size[1] = stride[1] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 1); size[2] = stride[2] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 2); offset[0] = 0; offset[1] = size[0]; offset[2] = offset[1] + size[1]; for (i = 0; i < 3; i++) { data = g_slice_new0 (GstEGLGLESImageData); glGenTextures (1, &data->texture); if (got_gl_error ("glGenTextures")) goto mem_error; glBindTexture (GL_TEXTURE_2D, data->texture); if (got_gl_error ("glBindTexture")) goto mem_error; /* Set 2D resizing params */ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* If these are not set the texture image unit will return * * (R, G, B, A) = black on glTexImage2D for non-POT width/height * * frames. For a deeper explanation take a look at the OpenGL ES * * documentation for glTexParameter */ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (got_gl_error ("glTexParameteri")) goto mem_error; glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info, i), GST_VIDEO_INFO_COMP_HEIGHT (&info, i), 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); if (got_gl_error ("glTexImage2D")) goto mem_error; image = eglCreateImageKHR (gst_egl_display_get (display), eglcontext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) (guintptr) data->texture, NULL); if (got_egl_error ("eglCreateImageKHR")) goto mem_error; mem[i] = gst_egl_image_allocator_wrap (allocator, display, image, GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, flags, size[i], data, (GDestroyNotify) gst_egl_gles_image_data_free); } n_mem = 3; } break; } case GST_VIDEO_FORMAT_RGBA: case GST_VIDEO_FORMAT_BGRA: case GST_VIDEO_FORMAT_ARGB: case GST_VIDEO_FORMAT_ABGR: case GST_VIDEO_FORMAT_RGBx: case GST_VIDEO_FORMAT_BGRx: case GST_VIDEO_FORMAT_xRGB: case GST_VIDEO_FORMAT_xBGR: case GST_VIDEO_FORMAT_AYUV:{ gsize size; EGLImageKHR image; mem[0] = gst_egl_image_allocator_alloc (allocator, display, GST_VIDEO_GL_TEXTURE_TYPE_RGBA, GST_VIDEO_INFO_WIDTH (&info), GST_VIDEO_INFO_HEIGHT (&info), &size); if (mem[0]) { stride[0] = size / GST_VIDEO_INFO_HEIGHT (&info); n_mem = 1; GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE); } else { data = g_slice_new0 (GstEGLGLESImageData); stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (&info) * 4); size = stride[0] * GST_VIDEO_INFO_HEIGHT (&info); glGenTextures (1, &data->texture); if (got_gl_error ("glGenTextures")) goto mem_error; glBindTexture (GL_TEXTURE_2D, data->texture); if (got_gl_error ("glBindTexture")) goto mem_error; /* Set 2D resizing params */ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* If these are not set the texture image unit will return * * (R, G, B, A) = black on glTexImage2D for non-POT width/height * * frames. For a deeper explanation take a look at the OpenGL ES * * documentation for glTexParameter */ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (got_gl_error ("glTexParameteri")) goto mem_error; glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, GST_VIDEO_INFO_WIDTH (&info), GST_VIDEO_INFO_HEIGHT (&info), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); if (got_gl_error ("glTexImage2D")) goto mem_error; image = eglCreateImageKHR (gst_egl_display_get (display), eglcontext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) (guintptr) data->texture, NULL); if (got_egl_error ("eglCreateImageKHR")) goto mem_error; mem[0] = gst_egl_image_allocator_wrap (allocator, display, image, GST_VIDEO_GL_TEXTURE_TYPE_RGBA, flags, size, data, (GDestroyNotify) gst_egl_gles_image_data_free); n_mem = 1; } break; } default: g_assert_not_reached (); break; } buffer = gst_buffer_new (); gst_buffer_add_video_meta_full (buffer, 0, format, width, height, GST_VIDEO_INFO_N_PLANES (&info), offset, stride); for (i = 0; i < n_mem; i++) gst_buffer_append_memory (buffer, mem[i]); return buffer; mem_error: { GST_ERROR_OBJECT (GST_CAT_DEFAULT, "Failed to create EGLImage"); if (data) gst_egl_gles_image_data_free (data); if (mem[0]) gst_memory_unref (mem[0]); if (mem[1]) gst_memory_unref (mem[1]); if (mem[2]) gst_memory_unref (mem[2]); return NULL; } }
bool FBO::init(int width, int height, GraphicsContext3D::Attributes attributes) { #if !USE(SHARED_TEXTURE_WEBGL) // 1. Allocate a graphic buffer sp<ISurfaceComposer> composer(ComposerService::getComposerService()); m_graphicBufferAlloc = composer->createGraphicBufferAlloc(); status_t error; PixelFormat format = attributes.alpha ? HAL_PIXEL_FORMAT_RGBA_8888 : HAL_PIXEL_FORMAT_RGBX_8888; m_grBuffer = m_graphicBufferAlloc->createGraphicBuffer(width, height, format, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_TEXTURE, &error); if (error != NO_ERROR) { LOGWEBGL(" failed to allocate GraphicBuffer, error = %d", error); return false; } void *addr = 0; if (m_grBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &addr) != NO_ERROR) { LOGWEBGL(" failed to lock the GraphicBuffer"); return false; } // WebGL requires all buffers to be initialized to 0. memset(addr, 0, width * height * 4); m_grBuffer->unlock(); ANativeWindowBuffer* clientBuf = m_grBuffer->getNativeBuffer(); if (clientBuf->handle == 0) { LOGWEBGL(" empty handle in GraphicBuffer"); return false; } // 2. Create an EGLImage from the graphic buffer const EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE }; m_image = eglCreateImageKHR(m_dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, attrs); if (GraphicsContext3DInternal::checkEGLError("eglCreateImageKHR") != EGL_SUCCESS) { LOGWEBGL("eglCreateImageKHR() failed"); return false; } #endif // 3. Create a texture from the EGLImage m_texture = createTexture(m_image, width, height); if (m_texture == 0) { LOGWEBGL("createTexture() failed"); return false; } // 4. Create the Framebuffer Object from the texture glGenFramebuffers(1, &m_fbo); if (attributes.depth) { glGenRenderbuffers(1, &m_depthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); if (GraphicsContext3DInternal::checkGLError("glRenderbufferStorage") != GL_NO_ERROR) return false; } if (attributes.stencil) { glGenRenderbuffers(1, &m_stencilBuffer); glBindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); if (GraphicsContext3DInternal::checkGLError("glRenderbufferStorage") != GL_NO_ERROR) return false; } glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0); if (GraphicsContext3DInternal::checkGLError("glFramebufferTexture2D") != GL_NO_ERROR) return false; if (attributes.depth) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer); if (GraphicsContext3DInternal::checkGLError("glFramebufferRenderbuffer") != GL_NO_ERROR) return false; } if (attributes.stencil) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilBuffer); if (GraphicsContext3DInternal::checkGLError("glFramebufferRenderbuffer") != GL_NO_ERROR) return false; } GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { LOGWEBGL("Framebuffer incomplete: %d", status); return false; } glBindFramebuffer(GL_FRAMEBUFFER, 0); return true; }
bool camera_read_frame(void){ if(MMAL_BUFFER_HEADER_T* buf = mmal_queue_get(video_queue)){ //mmal_buffer_header_mem_lock(buf); //printf("Buffer received with length %d\n", buf->length); glBindTexture(GL_TEXTURE_EXTERNAL_OES, cam_ytex); check(); if(yimg != EGL_NO_IMAGE_KHR){ eglDestroyImageKHR(GDisplay, yimg); yimg = EGL_NO_IMAGE_KHR; } yimg = eglCreateImageKHR(GDisplay, EGL_NO_CONTEXT, EGL_IMAGE_BRCM_MULTIMEDIA_Y, (EGLClientBuffer) buf->data, NULL); check(); glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, yimg); check(); glBindTexture(GL_TEXTURE_EXTERNAL_OES, cam_utex); check(); if(uimg != EGL_NO_IMAGE_KHR){ eglDestroyImageKHR(GDisplay, uimg); uimg = EGL_NO_IMAGE_KHR; } uimg = eglCreateImageKHR(GDisplay, EGL_NO_CONTEXT, EGL_IMAGE_BRCM_MULTIMEDIA_U, (EGLClientBuffer) buf->data, NULL); check(); glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, uimg); check(); glBindTexture(GL_TEXTURE_EXTERNAL_OES, cam_vtex); check(); if(vimg != EGL_NO_IMAGE_KHR){ eglDestroyImageKHR(GDisplay, vimg); vimg = EGL_NO_IMAGE_KHR; } vimg = eglCreateImageKHR(GDisplay, EGL_NO_CONTEXT, EGL_IMAGE_BRCM_MULTIMEDIA_V, (EGLClientBuffer) buf->data, NULL); check(); glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, vimg); check(); //mmal_buffer_header_mem_unlock(buf); mmal_buffer_header_release(buf); if(preview_port->is_enabled){ MMAL_STATUS_T status; MMAL_BUFFER_HEADER_T *new_buffer; new_buffer = mmal_queue_get(video_pool->queue); if (new_buffer) status = mmal_port_send_buffer(preview_port, new_buffer); if (!new_buffer || status != MMAL_SUCCESS) printf("Unable to return a buffer to the video port\n\n"); } return true; } return false; //no buffer received }
int main(void) { EGLint major, minor, eglCfgCount, eglCfgVisualId, width, height; const IMG_gralloc_module_public_t *module; buffer_handle_t srcBuffer, destBuffer; EGLImageKHR eglSrcImage, eglDestImage; EGLConfig eglConfig, eglFBConfig; GLuint fboName, textureNames[2]; EGLNativeWindowType eglWindow; EGLSurface eglWindowSurface; alloc_device_t *device; EGLContext eglContext; EGLDisplay eglDisplay; int err = 1, stride; GLenum glError; ANativeWindowBuffer sSrcBuffer = { .common.magic = ANDROID_NATIVE_BUFFER_MAGIC, .common.version = sizeof(ANativeWindowBuffer), .common.incRef = incRefNop, .common.decRef = decRefNop, .width = SRC_WIDTH, .height = SRC_HEIGHT, .stride = SRC_STRIDE, .usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, }; ANativeWindowBuffer sDestBuffer = { .common.magic = ANDROID_NATIVE_BUFFER_MAGIC, .common.version = sizeof(ANativeWindowBuffer), .common.incRef = incRefNop, .common.decRef = decRefNop, .width = DEST_WIDTH, .height = DEST_HEIGHT, .stride = DEST_STRIDE, .format = DEST_FORMAT, .usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, }; EGLint eglCfgAttribs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, EGL_ALPHA_SIZE, 0, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, #ifdef EGL_ANDROID_recordable EGL_RECORDABLE_ANDROID, EGL_TRUE, #endif EGL_NONE, }; const float srcVertexArray[2 * 4] = { 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, }; const float texCoordArray[2 * 4] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, }; const float destVertexArray[2 * 4] = { -1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, -1.0f, }; eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); if(eglDisplay == EGL_NO_DISPLAY) { printf("eglGetDisplay failed\n"); goto err_out; } if(!eglInitialize(eglDisplay, &major, &minor)) { printf("eglInitialize failed (err=0x%x)\n", eglGetError()); goto err_out; } if(!eglChooseConfig(eglDisplay, eglCfgAttribs, &eglConfig, 1, &eglCfgCount)) { printf("eglChooseConfig failed (err=0x%x)\n", eglGetError()); goto err_terminate; } if(!eglCfgCount) { printf("eglChooseConfig found no suitable configs\n"); goto err_terminate; } if(!eglGetConfigAttrib(eglDisplay, eglConfig, EGL_NATIVE_VISUAL_ID, &eglCfgVisualId)) { printf("eglGetConfigAttrib failed (err=0x%x)\n", eglGetError()); goto err_terminate; } sSrcBuffer.format = eglCfgVisualId; /* Handle FB rendering ***************************************************/ eglWindow = android_createDisplaySurface(); if(!eglWindow) { printf("android_createDisplaySurface returned NULL\n"); goto err_terminate; } eglWindow->common.incRef(&eglWindow->common); eglFBConfig = findMatchingWindowConfig(eglDisplay, EGL_OPENGL_ES_BIT, eglWindow); /* FIXME: findMatchingWindowConfig returns no error code */ eglContext = eglCreateContext(eglDisplay, eglFBConfig, EGL_NO_CONTEXT, NULL); if(eglContext == EGL_NO_CONTEXT) { printf("eglCreateContext failed (err=0x%x)\n", eglGetError()); goto err_window_decref; } eglWindowSurface = eglCreateWindowSurface(eglDisplay, eglFBConfig, eglWindow, NULL); if(eglWindowSurface == EGL_NO_SURFACE) { printf("eglCreateWindowSurface failed (err=0x%x)\n", eglGetError()); goto err_destroy_context; } if(!eglQuerySurface(eglDisplay, eglWindowSurface, EGL_WIDTH, &width)) { printf("eglQuerySurface #1 failed (err=0x%x)\n", eglGetError()); goto err_destroy_context; } if(!eglQuerySurface(eglDisplay, eglWindowSurface, EGL_HEIGHT, &height)) { printf("eglQuerySurface #2 failed (err=0x%x)\n", eglGetError()); goto err_destroy_context; } if(!eglMakeCurrent(eglDisplay, eglWindowSurface, eglWindowSurface, eglContext)) { printf("eglMakeCurrent failed (err=0x%x)\n", eglGetError()); goto err_destroy_surface; } /* Allocate some compatible buffers with gralloc *************************/ err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&module); if(err) { printf("hw_get_module failed (err=%d)\n", err); goto err_make_non_current; } err = module->base.common.methods->open((const hw_module_t *)module, GRALLOC_HARDWARE_GPU0, (hw_device_t **)&device); if(err) { printf("module->common.methods->open() failed (err=%d)\n", err); goto err_make_non_current; } err = device->alloc(device, SRC_WIDTH, SRC_HEIGHT, eglCfgVisualId, GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, &srcBuffer, &stride); if(err) { printf("device->alloc() failed (err=%d)\n", err); goto err_close; } err = device->alloc(device, DEST_WIDTH, DEST_HEIGHT, DEST_FORMAT, GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, &destBuffer, &stride); if(err) { printf("device->alloc() failed (err=%d)\n", err); goto err_free_src; } err = module->base.registerBuffer(&module->base, srcBuffer); if(err) { printf("module->registerBuffer() failed (err=%d)\n", err); goto err_free_dest; } err = module->base.registerBuffer(&module->base, destBuffer); if(err) { printf("module->registerBuffer() failed (err=%d)\n", err); goto err_unregister_src; } sSrcBuffer.handle = srcBuffer; sDestBuffer.handle = destBuffer; /* Make some EGLImageKHRs out of them ************************************/ eglSrcImage = eglCreateImageKHR(eglDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)&sSrcBuffer, 0); if(eglSrcImage == EGL_NO_IMAGE_KHR) { printf("eglCreateImageKHR #1 failed (err=0x%x)\n", eglGetError()); goto err_unregister_dest; } eglDestImage = eglCreateImageKHR(eglDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)&sDestBuffer, 0); if(eglDestImage == EGL_NO_IMAGE_KHR) { printf("eglCreateImageKHR #2 failed (err=0x%x)\n", eglGetError()); goto err_destroy_src_image; } /* Create funny textures *************************************************/ glGenTextures(2, textureNames); glError = glGetError(); if(glError != GL_NO_ERROR) { printf("glGenTextures generated error 0x%x\n", glError); goto err_destroy_dest_image; } glBindTexture(GL_TEXTURE_2D, textureNames[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglSrcImage); glError = glGetError(); if(glError != GL_NO_ERROR) { printf("glEGLImageTargetTexture2DOES generated error 0x%x\n", glError); goto err_delete_textures; } glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureNames[1]); glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, eglDestImage); glError = glGetError(); if(glError != GL_NO_ERROR) { printf("glEGLImageTargetTexture2DOES generated error 0x%x\n", glError); goto err_delete_textures; } /* Create FBO ************************************************************/ glGenFramebuffersOES(1, &fboName); glError = glGetError(); if(glError != GL_NO_ERROR) { printf("glGenFrameBuffersOES generated error 0x%x\n", glError); goto err_delete_textures; } glBindFramebufferOES(GL_FRAMEBUFFER_OES, fboName); glError = glGetError(); if(glError != GL_NO_ERROR) { printf("glBindFramebufferOES generated error 0x%x\n", glError); goto err_delete_framebuffer; } glBindTexture(GL_TEXTURE_2D, textureNames[0]); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, textureNames[0], 0); glError = glGetError(); if(glError != GL_NO_ERROR) { printf("glFramebufferTexture2DOES generated error 0x%x\n", glError); goto err_delete_framebuffer; } /*************************************************************************/ glError = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); if(glError != GL_FRAMEBUFFER_COMPLETE_OES) { printf("glCheckFramebufferStatus generated error 0x%x\n", glError); goto err_delete_framebuffer; } /* Draw some stuff */ { const float vertexArray[2 * 4] = { -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, }; const float colorArray[4 * 4] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, }; char dummy[4]; glViewport(0, 0, SRC_WIDTH, SRC_HEIGHT); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertexArray); glColorPointer(4, GL_FLOAT, 0, colorArray); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, dummy); } /* RGB -> YUV blit */ err = module->Blit2(module, srcBuffer, destBuffer, SRC_WIDTH, SRC_HEIGHT, 0, 0); if(err) { printf("module->Blit2() failed (err=%d)\n", err); goto err_delete_framebuffer; } /* Present both to screen (should appear identical) */ glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); glViewport(0, 0, width, height); glClearColor(0.0f, 1.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray); glEnable(GL_TEXTURE_EXTERNAL_OES); glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureNames[1]); glVertexPointer(2, GL_FLOAT, 0, destVertexArray); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisable(GL_TEXTURE_EXTERNAL_OES); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, textureNames[0]); glVertexPointer(2, GL_FLOAT, 0, srcVertexArray); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); eglSwapBuffers(eglDisplay, eglWindowSurface); sleep(1); err_delete_framebuffer: glDeleteFramebuffersOES(1, &fboName); err_delete_textures: glDeleteTextures(2, textureNames); err_destroy_dest_image: eglDestroyImageKHR(eglDisplay, eglDestImage); err_destroy_src_image: eglDestroyImageKHR(eglDisplay, eglSrcImage); err_unregister_dest: err = module->base.unregisterBuffer(&module->base, destBuffer); if(err) printf("module->unregisterBuffer() failed (err=%d)\n", err); err_unregister_src: err = module->base.unregisterBuffer(&module->base, srcBuffer); if(err) printf("module->unregisterBuffer() failed (err=%d)\n", err); err_free_dest: err = device->free(device, destBuffer); if(err) printf("device->free() failed (err=%d)\n", err); err_free_src: err = device->free(device, srcBuffer); if(err) printf("device->free() failed (err=%d)\n", err); err_close: err = device->common.close((hw_device_t *)device); if(err) printf("hal->close() failed (err=%d)\n", err); err_make_non_current: eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); err_destroy_surface: eglDestroySurface(eglDisplay, eglWindowSurface); err_destroy_context: eglDestroyContext(eglDisplay, eglContext); err_window_decref: eglWindow->common.decRef(&eglWindow->common); err_terminate: eglTerminate(eglDisplay); err_out: return err; }
extern "C" void Java_org_mozilla_testuniversalsurfacetexture_TestUniversalSurfaceTexture_attachTexture(JNIEnv* aJEnv, jclass klass, jobject aSurface, int aDestroyed) { __android_log_print(ANDROID_LOG_ERROR, "TUST", "### point a"); if (!sSurfaceClass) { sSurfaceClass = reinterpret_cast<jclass> (aJEnv->NewGlobalRef(aJEnv->FindClass("android/view/Surface"))); sNativeSurfaceField = aJEnv->GetFieldID(sSurfaceClass, "mNativeSurface", "I"); sSurfaceControlField = aJEnv->GetFieldID(sSurfaceClass, "mSurfaceControl", "I"); void* lib = dlopen("libui.so", RTLD_LAZY); sw_gralloc_handle_t_lock = (typeof(sw_gralloc_handle_t_lock)) dlsym(lib, "_ZN7android19sw_gralloc_handle_t4lockEPS0_iiiiiPPv"); sw_gralloc_handle_t_unlock = (typeof(sw_gralloc_handle_t_unlock)) dlsym(lib, "_ZN7android19sw_gralloc_handle_t6unlockEPS0_"); __android_log_print(ANDROID_LOG_ERROR, "TUST", "### Lock=%p, unlock=%p", sw_gralloc_handle_t_lock, sw_gralloc_handle_t_unlock); lib = dlopen("libhardware.so", RTLD_LAZY); hw_get_module = (typeof(hw_get_module))dlsym(lib, "hw_get_module"); hw_module_t* pModule; hw_get_module("gralloc", &pModule); sModule = reinterpret_cast<gralloc_module_t*>(pModule); __android_log_print(ANDROID_LOG_ERROR, "TUST", "### Gralloc module=%p", pModule); } if (!sImage) { ANativeWindow* nativeWindow = reinterpret_cast<ANativeWindow*> (aJEnv->GetIntField(aSurface, sNativeSurfaceField) + 8); /*Rect rect; rect.left = rect.top = rect.right = rect.bottom = 0; nativeWindow->perform(nativeWindow, NATIVE_WINDOW_SET_CROP, &rect);*/ // NB: nativeWindow->common.magic is '_wnd' as a FourCC. // My version is 104. __android_log_print(ANDROID_LOG_ERROR, "TUST", "### Native window ptr %p, magic %08x, version %d, reserved %p, flags %d, dpi %g\n", nativeWindow, (unsigned)nativeWindow->common.magic, nativeWindow->common.version, nativeWindow->common.reserved[0], (int)nativeWindow->flags, (double)nativeWindow->xdpi); nativeWindow->dequeueBuffer(nativeWindow, &sBuffer); nativeWindow->lockBuffer(nativeWindow, sBuffer); // Must increment the refcount on the native window to avoid crashes on Mali (Galaxy S2). nativeWindow->common.incRef(&nativeWindow->common); const EGLint eglImgAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE }; sBuffer->common.incRef(&sBuffer->common); sImage = eglCreateImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, reinterpret_cast<EGLClientBuffer>(sBuffer), eglImgAttrs); //nativeWindow->queueBuffer(nativeWindow, sBuffer); } uint8_t *bits = 0; int err = sModule->lock(sModule, sBuffer->handle, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, 0, 0, 512, 512, (void**)&bits); __android_log_print(ANDROID_LOG_ERROR, "TUST", "### Buffer width=%d height=%d stride=%d format=%d usage=%d Bits are: %p, err=%d", sBuffer->width, sBuffer->height, sBuffer->stride, sBuffer->format, sBuffer->usage, bits, err); struct timeval tv; gettimeofday(&tv, NULL); static int x = 0; for (int i = 0; i < 512*512*2; i += 2) { bits[i] = bits[i+1] = (tv.tv_usec / 100000) % 256; } sModule->unlock(sModule, sBuffer->handle); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, sImage); __android_log_print(ANDROID_LOG_ERROR, "TUST", "### Success! GL error is: %d", (int)glGetError()); }