@ -10,366 +10,262 @@
# include <wlr/render/interface.h>
# include <wlr/render/interface.h>
# include <wlr/types/wlr_matrix.h>
# include <wlr/types/wlr_matrix.h>
# include <wlr/util/log.h>
# include <wlr/util/log.h>
# include "glapi.h"
# include "render/gles2.h"
# include "render/gles2.h"
# include "util/signal.h"
# include "util/signal.h"
static struct gles2_pixel_format external_pixel_format = {
. wl_format = 0 ,
. depth = 0 ,
. bpp = 0 ,
. gl_format = 0 ,
. gl_type = 0 ,
} ;
static void gles2_texture_ensure ( struct wlr_gles2_texture * texture ,
GLenum target ) {
if ( texture - > tex_id ) {
return ;
}
texture - > target = target ;
glGenTextures ( 1 , & texture - > tex_id ) ;
glBindTexture ( target , texture - > tex_id ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
}
static const struct wlr_texture_impl texture_impl ;
static const struct wlr_texture_impl texture_impl ;
struct wlr_gles2_texture * gles2_get_texture ( struct wlr_texture * wlr_texture ) {
static struct wlr_gles2_texture * gles2_get_texture (
struct wlr_texture * wlr_texture ) {
assert ( wlr_texture - > impl = = & texture_impl ) ;
assert ( wlr_texture - > impl = = & texture_impl ) ;
return ( struct wlr_gles2_texture * ) wlr_texture ;
return ( struct wlr_gles2_texture * ) wlr_texture ;
}
}
static bool gles2_texture_upload_pixels ( struct wlr_texture * wlr_texture ,
struct wlr_gles2_texture * gles2_get_texture_in_context (
enum wl_shm_format format , int stride , int width , int height ,
struct wlr_texture * wlr_texture ) {
const unsigned char * pixels ) {
struct wlr_gles2_texture * texture = gles2_get_texture ( wlr_texture ) ;
struct wlr_gles2_texture * texture = gles2_get_texture ( wlr_texture ) ;
assert ( eglGetCurrentContext ( ) = = texture - > renderer - > egl - > context ) ;
const struct gles2_pixel_format * fmt = gles2_format_from_wl ( format ) ;
return texture ;
if ( ! fmt | | ! fmt - > gl_format ) {
wlr_log ( L_ERROR , " No supported pixel format for this texture " ) ;
return false ;
}
texture - > wlr_texture . width = width ;
texture - > wlr_texture . height = height ;
texture - > wlr_texture . format = format ;
texture - > pixel_format = fmt ;
GLES2_DEBUG_PUSH ;
gles2_texture_ensure ( texture , GL_TEXTURE_2D ) ;
glBindTexture ( GL_TEXTURE_2D , texture - > tex_id ) ;
glPixelStorei ( GL_UNPACK_ROW_LENGTH_EXT , stride ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , fmt - > gl_format , width , height , 0 ,
fmt - > gl_format , fmt - > gl_type , pixels ) ;
GLES2_DEBUG_POP ;
texture - > wlr_texture . valid = true ;
return true ;
}
}
static bool gles2_texture_update_pixels ( struct wlr_texture * wlr_texture ,
static void gles2_texture_get_size ( struct wlr_texture * wlr_texture , int * width ,
enum wl_shm_format format , int stride , int x , int y ,
int * height ) {
int width , int height , const unsigned char * pixels ) {
struct wlr_gles2_texture * texture = gles2_get_texture ( wlr_texture ) ;
struct wlr_gles2_texture * texture = gles2_get_texture ( wlr_texture ) ;
* width = texture - > width ;
// TODO: Test if the unpack subimage extension is supported and adjust the
* height = texture - > height ;
// upload strategy if not
if ( ! texture - > wlr_texture . valid
| | texture - > wlr_texture . format ! = format
/* || unpack not supported */ ) {
return gles2_texture_upload_pixels ( & texture - > wlr_texture , format ,
stride , width , height , pixels ) ;
}
const struct gles2_pixel_format * fmt = texture - > pixel_format ;
GLES2_DEBUG_PUSH ;
glBindTexture ( GL_TEXTURE_2D , texture - > tex_id ) ;
glPixelStorei ( GL_UNPACK_ROW_LENGTH_EXT , stride ) ;
glPixelStorei ( GL_UNPACK_SKIP_PIXELS_EXT , x ) ;
glPixelStorei ( GL_UNPACK_SKIP_ROWS_EXT , y ) ;
glTexSubImage2D ( GL_TEXTURE_2D , 0 , x , y , width , height , fmt - > gl_format ,
fmt - > gl_type , pixels ) ;
glPixelStorei ( GL_UNPACK_SKIP_PIXELS_EXT , 0 ) ;
glPixelStorei ( GL_UNPACK_SKIP_ROWS_EXT , 0 ) ;
GLES2_DEBUG_POP ;
return true ;
}
}
static bool gles2_texture_upload_shm ( struct wlr_texture * wlr_texture ,
static bool gles2_texture_write_pixels ( struct wlr_texture * wlr_texture ,
uint32_t format , struct wl_shm_buffer * buffer ) {
enum wl_shm_format wl_fmt , uint32_t stride , uint32_t width ,
struct wlr_gles2_texture * texture = gles2_get_texture ( wlr_texture ) ;
uint32_t height , uint32_t src_x , uint32_t src_y , uint32_t dst_x ,
uint32_t dst_y , const void * data ) {
struct wlr_gles2_texture * texture =
gles2_get_texture_in_context ( wlr_texture ) ;
if ( texture - > type ! = WLR_GLES2_TEXTURE_GLTEX ) {
wlr_log ( L_ERROR , " Cannot write pixels to immutable texture " ) ;
return false ;
}
const struct gles2_pixel_format * fmt = gles2_format_from_wl ( format ) ;
const struct gles2_pixel_format * fmt = gles2_format_from_wl ( wl_fmt ) ;
if ( ! fmt | | ! fmt - > gl_format ) {
if ( fmt = = NULL ) {
wlr_log ( L_ERROR , " Unsupported pixel format % " PRIu32 " for this texture " ,
wlr_log ( L_ERROR , " Unsupported pixel format % " PRIu32 , wl_fmt ) ;
format ) ;
return false ;
return false ;
}
}
wl_shm_buffer_begin_access ( buffer ) ;
uint8_t * pixels = wl_shm_buffer_get_data ( buffer ) ;
int width = wl_shm_buffer_get_width ( buffer ) ;
int height = wl_shm_buffer_get_height ( buffer ) ;
int pitch = wl_shm_buffer_get_stride ( buffer ) / ( fmt - > bpp / 8 ) ;
texture - > wlr_texture . width = width ;
texture - > wlr_texture . height = height ;
texture - > wlr_texture . format = format ;
texture - > pixel_format = fmt ;
// TODO: what if the unpack subimage extension isn't supported?
GLES2_DEBUG_PUSH ;
GLES2_DEBUG_PUSH ;
gles2_texture_ensure ( texture , GL_TEXTURE_2D ) ;
glBindTexture ( GL_TEXTURE_2D , texture - > tex_id ) ;
glPixelStorei ( GL_UNPACK_ROW_LENGTH_EXT , pitch ) ;
glPixelStorei ( GL_UNPACK_SKIP_PIXELS_EXT , 0 ) ;
glPixelStorei ( GL_UNPACK_SKIP_ROWS_EXT , 0 ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , fmt - > gl_format , width , height , 0 ,
fmt - > gl_format , fmt - > gl_type , pixels ) ;
GLES2_DEBUG_POP ;
texture - > wlr_texture . valid = true ;
glBindTexture ( GL_TEXTURE_2D , texture - > gl_tex ) ;
wl_shm_buffer_end_access ( buffer ) ;
return true ;
}
static bool gles2_texture_update_shm ( struct wlr_texture * wlr_texture ,
glPixelStorei ( GL_UNPACK_ROW_LENGTH_EXT , stride / ( fmt - > bpp / 8 ) ) ;
uint32_t format , int x , int y , int width , int height ,
glPixelStorei ( GL_UNPACK_SKIP_PIXELS_EXT , src_x ) ;
struct wl_shm_buffer * buffer ) {
glPixelStorei ( GL_UNPACK_SKIP_ROWS_EXT , src_y ) ;
struct wlr_gles2_texture * texture = gles2_get_texture ( wlr_texture ) ;
// TODO: Test if the unpack subimage extension is supported and adjust the
glTexSubImage2D ( GL_TEXTURE_2D , 0 , dst_x , dst_y , width , height ,
// upload strategy if not
fmt - > gl_format , fmt - > gl_type , data ) ;
assert ( texture ) ;
if ( ! texture - > wlr_texture . valid
| | texture - > wlr_texture . format ! = format
/* || unpack not supported */ ) {
return gles2_texture_upload_shm ( & texture - > wlr_texture , format , buffer ) ;
}
const struct gles2_pixel_format * fmt = texture - > pixel_format ;
wl_shm_buffer_begin_access ( buffer ) ;
uint8_t * pixels = wl_shm_buffer_get_data ( buffer ) ;
int pitch = wl_shm_buffer_get_stride ( buffer ) / ( fmt - > bpp / 8 ) ;
GLES2_DEBUG_PUSH ;
glPixelStorei ( GL_UNPACK_ROW_LENGTH_EXT , 0 ) ;
glBindTexture ( GL_TEXTURE_2D , texture - > tex_id ) ;
glPixelStorei ( GL_UNPACK_ROW_LENGTH_EXT , pitch ) ;
glPixelStorei ( GL_UNPACK_SKIP_PIXELS_EXT , x ) ;
glPixelStorei ( GL_UNPACK_SKIP_ROWS_EXT , y ) ;
glTexSubImage2D ( GL_TEXTURE_2D , 0 , x , y , width , height ,
fmt - > gl_format , fmt - > gl_type , pixels ) ;
glPixelStorei ( GL_UNPACK_SKIP_PIXELS_EXT , 0 ) ;
glPixelStorei ( GL_UNPACK_SKIP_PIXELS_EXT , 0 ) ;
glPixelStorei ( GL_UNPACK_SKIP_ROWS_EXT , 0 ) ;
glPixelStorei ( GL_UNPACK_SKIP_ROWS_EXT , 0 ) ;
GLES2_DEBUG_POP ;
wl_shm_buffer_end_access ( buffer ) ;
GLES2_DEBUG_POP ;
return true ;
return true ;
}
}
static bool gles2_texture_upload_drm ( struct wlr_texture * wlr_texture ,
static void gles2_texture_destroy ( struct wlr_texture * wlr_texture ) {
struct wl_resource * buf ) {
if ( wlr_texture = = NULL ) {
struct wlr_gles2_texture * tex = gles2_get_texture ( wlr_texture ) ;
return ;
if ( ! glEGLImageTargetTexture2DOES ) {
return false ;
}
}
EGLint format ;
struct wlr_gles2_texture * texture = gles2_get_texture ( wlr_texture ) ;
if ( ! wlr_egl_query_buffer ( tex - > egl , buf , EGL_TEXTURE_FORMAT , & format ) ) {
wlr_log ( L_INFO , " upload_drm called with no drm buffer " ) ;
return false ;
}
wlr_egl_query_buffer ( tex - > egl , buf , EGL_WIDTH ,
wlr_egl_make_current ( texture - > renderer - > egl , EGL_NO_SURFACE , NULL ) ;
( EGLint * ) & tex - > wlr_texture . width ) ;
wlr_egl_query_buffer ( tex - > egl , buf , EGL_HEIGHT ,
( EGLint * ) & tex - > wlr_texture . height ) ;
EGLint inverted_y ;
GLES2_DEBUG_PUSH ;
if ( wlr_egl_query_buffer ( tex - > egl , buf , EGL_WAYLAND_Y_INVERTED_WL ,
& inverted_y ) ) {
if ( texture - > image_tex ) {
tex - > wlr_texture . inverted_y = ! ! inverted_y ;
glDeleteTextures ( 1 , & texture - > image_tex ) ;
}
if ( texture - > image ) {
assert ( eglDestroyImageKHR ) ;
eglDestroyImageKHR ( texture - > renderer - > egl - > display , texture - > image ) ;
}
}
GLenum target ;
if ( texture - > type = = WLR_GLES2_TEXTURE_GLTEX ) {
const struct gles2_pixel_format * pf ;
glDeleteTextures ( 1 , & texture - > gl_tex ) ;
switch ( format ) {
case EGL_TEXTURE_RGB :
case EGL_TEXTURE_RGBA :
target = GL_TEXTURE_2D ;
pf = gles2_format_from_wl ( WL_SHM_FORMAT_ARGB8888 ) ;
break ;
case EGL_TEXTURE_EXTERNAL_WL :
target = GL_TEXTURE_EXTERNAL_OES ;
pf = & external_pixel_format ;
break ;
default :
wlr_log ( L_ERROR , " invalid/unsupported egl buffer format " ) ;
return false ;
}
}
GLES2_DEBUG_PUSH ;
gles2_texture_ensure ( tex , target ) ;
glBindTexture ( GL_TEXTURE_2D , tex - > tex_id ) ;
GLES2_DEBUG_POP ;
GLES2_DEBUG_POP ;
EGLint attribs [ ] = { EGL_WAYLAND_PLANE_WL , 0 , EGL_NONE } ;
free ( texture ) ;
}
if ( tex - > image ) {
static const struct wlr_texture_impl texture_impl = {
wlr_egl_destroy_image ( tex - > egl , tex - > image ) ;
. get_size = gles2_texture_get_size ,
. write_pixels = gles2_texture_write_pixels ,
. destroy = gles2_texture_destroy ,
} ;
struct wlr_texture * gles2_texture_from_pixels ( struct wlr_renderer * wlr_renderer ,
enum wl_shm_format wl_fmt , uint32_t stride , uint32_t width ,
uint32_t height , const void * data ) {
struct wlr_gles2_renderer * renderer =
gles2_get_renderer_in_context ( wlr_renderer ) ;
const struct gles2_pixel_format * fmt = gles2_format_from_wl ( wl_fmt ) ;
if ( fmt = = NULL ) {
wlr_log ( L_ERROR , " Unsupported pixel format % " PRIu32 , wl_fmt ) ;
return NULL ;
}
}
tex - > image = wlr_egl_create_image ( tex - > egl , EGL_WAYLAND_BUFFER_WL ,
struct wlr_gles2_texture * texture =
( EGLClientBuffer * ) buf , attribs ) ;
calloc ( 1 , sizeof ( struct wlr_gles2_texture ) ) ;
if ( ! tex - > image ) {
if ( texture = = NULL ) {
wlr_log ( L_ERROR , " failed to create EGL image " ) ;
wlr_log ( L_ERROR , " Allocation failed " ) ;
return false ;
return NULL ;
}
}
wlr_texture_init ( & texture - > wlr_texture , & texture_impl ) ;
texture - > renderer = renderer ;
texture - > width = width ;
texture - > height = height ;
texture - > type = WLR_GLES2_TEXTURE_GLTEX ;
texture - > has_alpha = fmt - > has_alpha ;
GLES2_DEBUG_PUSH ;
GLES2_DEBUG_PUSH ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( target , tex - > tex_id ) ;
glEGLImageTargetTexture2DOES ( target , tex - > image ) ;
GLES2_DEBUG_POP ;
tex - > wlr_texture . valid = true ;
tex - > pixel_format = pf ;
return true ;
}
static bool gles2_texture_upload_eglimage ( struct wlr_texture * wlr_texture ,
glGenTextures ( 1 , & texture - > gl_tex ) ;
EGLImageKHR image , uint32_t width , uint32_t height ) {
glBindTexture ( GL_TEXTURE_2D , texture - > gl_tex ) ;
struct wlr_gles2_texture * tex = gles2_get_texture ( wlr_texture ) ;
tex - > image = image ;
glPixelStorei ( GL_UNPACK_ROW_LENGTH_EXT , stride / ( fmt - > bpp / 8 ) ) ;
tex - > pixel_format = & external_pixel_format ;
glTexImage2D ( GL_TEXTURE_2D , 0 , fmt - > gl_format , width , height , 0 ,
tex - > wlr_texture . valid = true ;
fmt - > gl_format , fmt - > gl_type , data ) ;
tex - > wlr_texture . width = width ;
glPixelStorei ( GL_UNPACK_ROW_LENGTH_EXT , 0 ) ;
tex - > wlr_texture . height = height ;
GLES2_DEBUG_PUSH ;
gles2_texture_ensure ( tex , GL_TEXTURE_2D ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_EXTERNAL_OES , tex - > tex_id ) ;
glEGLImageTargetTexture2DOES ( GL_TEXTURE_EXTERNAL_OES , tex - > image ) ;
GLES2_DEBUG_POP ;
GLES2_DEBUG_POP ;
return ( struct wlr_texture * ) texture ;
return true ;
}
}
static bool gles2_texture_upload_dmabuf ( struct wlr_texture * wlr_texture ,
struct wlr_texture * gles2_texture_from_wl_drm ( struct wlr_renderer * wlr_renderer ,
struct wl_resource * dmabuf_resource ) {
struct wl_resource * data ) {
struct wlr_gles2_texture * tex = gles2_get_texture ( wlr_texture ) ;
struct wlr_gles2_renderer * renderer = gles2_get_renderer ( wlr_renderer ) ;
struct wlr_dmabuf_buffer * dmabuf =
wlr_dmabuf_buffer_from_buffer_resource ( dmabuf_resource ) ;
if ( ! tex- > egl - > egl_exts . dmabuf_import ) {
if ( ! eglQueryWaylandBufferWL | | ! eglCreateImageKHR | |
wlr_log ( L_ERROR , " Want dmabuf but extension not present " ) ;
! glEGLImageTargetTexture2DOES ) {
return false ;
return NULL ;
}
}
tex - > wlr_texture . width = dmabuf - > attributes . width ;
EGLint fmt ;
tex - > wlr_texture . height = dmabuf - > attributes . height ;
if ( ! eglQueryWaylandBufferWL ( renderer - > egl - > display , data ,
EGL_TEXTURE_FORMAT , & fmt ) ) {
return NULL ;
}
if ( tex - > image ) {
EGLint width , height ;
wlr_egl_destroy_image ( tex - > egl , tex - > image ) ;
eglQueryWaylandBufferWL ( renderer - > egl - > display , data , EGL_WIDTH , & width ) ;
eglQueryWaylandBufferWL ( renderer - > egl - > display , data , EGL_HEIGHT , & height ) ;
EGLint inverted_y ;
if ( ! eglQueryWaylandBufferWL ( renderer - > egl - > display , data ,
EGL_WAYLAND_Y_INVERTED_WL , & inverted_y ) ) {
inverted_y = 0 ;
}
}
if ( wlr_dmabuf_buffer_has_inverted_y ( dmabuf ) ) {
struct wlr_gles2_texture * texture =
wlr_texture - > inverted_y = true ;
calloc ( 1 , sizeof ( struct wlr_gles2_texture ) ) ;
if ( texture = = NULL ) {
wlr_log ( L_ERROR , " Allocation failed " ) ;
return NULL ;
}
}
wlr_texture_init ( & texture - > wlr_texture , & texture_impl ) ;
texture - > renderer = renderer ;
texture - > width = width ;
texture - > height = height ;
texture - > wl_drm = data ;
texture - > inverted_y = ! ! inverted_y ;
GLenum target ;
GLenum target ;
const struct gles2_pixel_format * pf ;
switch ( fmt ) {
if ( dmabuf - > attributes . n_planes > 1 ) {
case EGL_TEXTURE_RGB :
target = GL_TEXTURE_EXTERNAL_OES ;
case EGL_TEXTURE_RGBA :
pf = & external_pixel_format ;
} else {
target = GL_TEXTURE_2D ;
target = GL_TEXTURE_2D ;
pf = gles2_format_from_wl ( WL_SHM_FORMAT_ARGB8888 ) ;
texture - > type = WLR_GLES2_TEXTURE_WL_DRM_GL ;
texture - > has_alpha = fmt = = EGL_TEXTURE_RGBA ;
break ;
case EGL_TEXTURE_EXTERNAL_WL :
target = GL_TEXTURE_EXTERNAL_OES ;
texture - > type = WLR_GLES2_TEXTURE_WL_DRM_EXT ;
texture - > has_alpha = true ;
break ;
default :
wlr_log ( L_ERROR , " Invalid or unsupported EGL buffer format " ) ;
free ( texture ) ;
return NULL ;
}
}
GLES2_DEBUG_PUSH ;
gles2_texture_ensure ( tex , target ) ;
glBindTexture ( target , tex - > tex_id ) ;
tex - > image = wlr_egl_create_image_from_dmabuf ( tex - > egl , & dmabuf - > attributes ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glEGLImageTargetTexture2DOES ( target , tex - > image ) ;
GLES2_DEBUG_POP ;
tex - > pixel_format = pf ;
tex - > wlr_texture . valid = true ;
return true ;
}
static bool gles2_texture_get_dmabuf_size ( struct wlr_texture * texture , struct
EGLint attribs [ ] = {
wl_resource * resource , int * width , int * height ) {
EGL_WAYLAND_PLANE_WL , 0 ,
if ( ! wlr_dmabuf_resource_is_buffer ( resource ) ) {
EGL_NONE ,
return false ;
} ;
texture - > image = eglCreateImageKHR ( renderer - > egl - > display ,
renderer - > egl - > context , EGL_WAYLAND_BUFFER_WL , data , attribs ) ;
if ( texture - > image = = NULL ) {
free ( texture ) ;
return NULL ;
}
}
struct wlr_dmabuf_buffer * dmabuf =
GLES2_DEBUG_PUSH ;
wlr_dmabuf_buffer_from_buffer_resource ( resource ) ;
* width = dmabuf - > attributes . width ;
* height = dmabuf - > attributes . height ;
return true ;
}
static void gles2_texture_get_buffer_size ( struct wlr_texture * texture ,
struct wl_resource * resource , int * width , int * height ) {
struct wl_shm_buffer * buffer = wl_shm_buffer_get ( resource ) ;
if ( ! buffer ) {
struct wlr_gles2_texture * tex = ( struct wlr_gles2_texture * ) texture ;
if ( ! glEGLImageTargetTexture2DOES ) {
return ;
}
if ( ! wlr_egl_query_buffer ( tex - > egl , resource , EGL_WIDTH ,
( EGLint * ) width ) ) {
if ( ! gles2_texture_get_dmabuf_size ( texture , resource , width ,
height ) ) {
wlr_log ( L_ERROR , " could not get size of the buffer " ) ;
return ;
}
}
wlr_egl_query_buffer ( tex - > egl , resource , EGL_HEIGHT , ( EGLint * ) height ) ;
return ;
glGenTextures ( 1 , & texture - > image_tex ) ;
}
glBindTexture ( target , texture - > image_tex ) ;
glEGLImageTargetTexture2DOES ( target , texture - > image ) ;
* width = wl_shm_buffer_get_width ( buffer ) ;
GLES2_DEBUG_POP ;
* height = wl_shm_buffer_get_height ( buffer ) ;
return ( struct wlr_texture * ) texture ;
}
}
static void gles2_texture_destroy ( struct wlr_texture * wlr_texture ) {
struct wlr_texture * gles2_texture_from_dmabuf ( struct wlr_renderer * wlr_renderer ,
struct wlr_gles2_texture * texture = gles2_get_texture ( wlr_texture ) ;
struct wlr_dmabuf_buffer_attribs * attribs ) {
struct wlr_gles2_renderer * renderer = gles2_get_renderer ( wlr_renderer ) ;
wlr_signal_emit_safe ( & texture - > wlr_texture . destroy_signal ,
if ( ! glEGLImageTargetTexture2DOES ) {
& texture - > wlr_texture ) ;
return NULL ;
if ( texture - > tex_id ) {
GLES2_DEBUG_PUSH ;
glDeleteTextures ( 1 , & texture - > tex_id ) ;
GLES2_DEBUG_POP ;
}
}
if ( texture - > image ) {
if ( ! renderer - > egl - > egl_exts . dmabuf_import ) {
wlr_egl_destroy_image ( texture - > egl , texture - > image ) ;
wlr_log ( L_ERROR , " Cannot create DMA-BUF texture: EGL extension "
" unavailable " ) ;
return NULL ;
}
}
free ( texture ) ;
struct wlr_gles2_texture * texture =
}
calloc ( 1 , sizeof ( struct wlr_gles2_texture ) ) ;
if ( texture = = NULL ) {
static const struct wlr_texture_impl texture_impl = {
wlr_log ( L_ERROR , " Allocation failed " ) ;
. upload_pixels = gles2_texture_upload_pixels ,
. update_pixels = gles2_texture_update_pixels ,
. upload_shm = gles2_texture_upload_shm ,
. update_shm = gles2_texture_update_shm ,
. upload_drm = gles2_texture_upload_drm ,
. upload_dmabuf = gles2_texture_upload_dmabuf ,
. upload_eglimage = gles2_texture_upload_eglimage ,
. get_buffer_size = gles2_texture_get_buffer_size ,
. destroy = gles2_texture_destroy ,
} ;
struct wlr_texture * gles2_texture_create ( struct wlr_egl * egl ) {
struct wlr_gles2_texture * texture ;
if ( ! ( texture = calloc ( 1 , sizeof ( struct wlr_gles2_texture ) ) ) ) {
return NULL ;
return NULL ;
}
}
wlr_texture_init ( & texture - > wlr_texture , & texture_impl ) ;
wlr_texture_init ( & texture - > wlr_texture , & texture_impl ) ;
texture - > egl = egl ;
texture - > renderer = renderer ;
return & texture - > wlr_texture ;
texture - > width = attribs - > width ;
texture - > height = attribs - > height ;
texture - > type = WLR_GLES2_TEXTURE_DMABUF ;
texture - > has_alpha = true ;
texture - > inverted_y =
( attribs - > flags & WLR_DMABUF_BUFFER_ATTRIBS_FLAGS_Y_INVERT ) ! = 0 ;
texture - > image = wlr_egl_create_image_from_dmabuf ( renderer - > egl , attribs ) ;
if ( texture - > image = = NULL ) {
free ( texture ) ;
return NULL ;
}
GLES2_DEBUG_PUSH ;
glGenTextures ( 1 , & texture - > image_tex ) ;
glBindTexture ( GL_TEXTURE_EXTERNAL_OES , texture - > image_tex ) ;
glEGLImageTargetTexture2DOES ( GL_TEXTURE_EXTERNAL_OES , texture - > image ) ;
GLES2_DEBUG_POP ;
return ( struct wlr_texture * ) texture ;
}
}