Signed-off-by: Ilyes Gouta <ilyes.go...@gmail.com> --- src/gallium/state_trackers/egl/Makefile.am | 9 + src/gallium/state_trackers/egl/common/native.h | 3 + .../state_trackers/egl/directfb/native_directfb.c | 585 +++++++++++++++++++++ 3 files changed, 597 insertions(+) create mode 100644 src/gallium/state_trackers/egl/directfb/native_directfb.c
diff --git a/src/gallium/state_trackers/egl/Makefile.am b/src/gallium/state_trackers/egl/Makefile.am index f78b36e..27925b9 100644 --- a/src/gallium/state_trackers/egl/Makefile.am +++ b/src/gallium/state_trackers/egl/Makefile.am @@ -102,3 +102,12 @@ AM_CPPFLAGS += \ -I$(top_srcdir)/src/gallium/winsys/sw \ -DHAVE_NULL_BACKEND endif + +if HAVE_EGL_PLATFORM_DIRECTFB +libegl_la_SOURCES += directfb/native_directfb.c +AM_CPPFLAGS += \ + -I$(top_srcdir)/src/gallium/winsys/sw \ + -DHAVE_DIRECTFB_BACKEND +AM_CFLAGS += \ + $(DIRECTFB_CFLAGS) +endif diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h index 312b079..553d8f9 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -336,6 +336,9 @@ native_get_null_platform(const struct native_event_handler *event_handler); const struct native_platform * native_get_android_platform(const struct native_event_handler *event_handler); +const struct native_platform * +native_get_directfb_platform(const struct native_event_handler *event_handler); + #ifdef __cplusplus } #endif diff --git a/src/gallium/state_trackers/egl/directfb/native_directfb.c b/src/gallium/state_trackers/egl/directfb/native_directfb.c new file mode 100644 index 0000000..6c3be7d --- /dev/null +++ b/src/gallium/state_trackers/egl/directfb/native_directfb.c @@ -0,0 +1,585 @@ +/* + * Copyright (C) 2013 Ilyes Gouta, ilyes.go...@gmail.com. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/** + * For DirectFB window system, + * + * - the only valid native display is EGL_DEFAULT_DISPLAY + */ + +#include <stdio.h> +#include <time.h> + +#include <directfb.h> + +#include "util/u_memory.h" +#include "util/u_format.h" +#include "util/u_debug.h" +#include "util/u_inlines.h" +#include "directfb/directfb_sw_winsys.h" + +#include "common/native_helper.h" +#include "common/native.h" + +struct directfb_display { + struct native_display base; + const struct native_event_handler *event_handler; + IDirectFBSurface *pSurface; + struct native_config *configs; + int num_configs; +}; + +struct directfb_surface { + struct native_surface base; + enum pipe_format format; + struct directfb_display *display; + IDirectFBSurface *pSurface; + unsigned int server_stamp; + unsigned int client_stamp; + struct resource_surface *rsurf; +}; + +static INLINE struct directfb_display* +directfb_display( const struct native_display *ndpy ) +{ + return (struct directfb_display*)ndpy; +} + +static INLINE struct directfb_surface* +directfb_surface( const struct native_surface *nsurf ) +{ + return (struct directfb_surface*)nsurf; +} + +static const struct native_config ** +directfb_display_get_configs( struct native_display *ndpy, int *num_configs ) +{ + struct directfb_display *display = + directfb_display( ndpy ); + const struct native_config **configs; + int i; + + configs = MALLOC( sizeof(*configs) * display->num_configs ); + if (configs) { + for (i = 0; i < display->num_configs; i++) + configs[i] = &display->configs[i]; + if (num_configs) + *num_configs = display->num_configs; + } + + return configs; +} + +static int +directfb_display_get_param( struct native_display *ndpy, + enum native_param_type param ) +{ + int val = 0; + + switch (param) { + case NATIVE_PARAM_PRESERVE_BUFFER: + case NATIVE_PARAM_USE_NATIVE_BUFFER: + val = 1; + break; + case NATIVE_PARAM_MAX_SWAP_INTERVAL: + default: + val = 0; + break; + } + + return val; +} + +static void +directfb_display_destroy( struct native_display *ndpy ) +{ + struct directfb_display *display = + directfb_display( ndpy ); + + FREE( display->configs ); + ndpy_uninit( &display->base ); + FREE( display ); +} + +static boolean +directfb_display_init_config( struct native_display *ndpy ) +{ + const enum pipe_format formats[] = { + PIPE_FORMAT_B8G8R8A8_UNORM, + PIPE_FORMAT_B5G6R5_UNORM, + PIPE_FORMAT_NONE + }; + + struct directfb_display *display = + directfb_display( ndpy ); + + display->configs = + CALLOC( 2 * Elements(formats) - 1, + sizeof( *display->configs ) ); + + if (!display->configs) + return FALSE; + + struct native_config *nconf; + + for (int i = 0; formats[i] != PIPE_FORMAT_NONE; i++) { + struct pipe_screen* screen = display->base.screen; + if (screen->is_format_supported( display->base.screen, + formats[i], + PIPE_TEXTURE_2D, + 0, + PIPE_BIND_RENDER_TARGET + | PIPE_BIND_DISPLAY_TARGET )) { + nconf = &display->configs[display->num_configs++]; + nconf->color_format = formats[i]; + nconf->buffer_mask = (1 << NATIVE_ATTACHMENT_BACK_LEFT) + | (1 << NATIVE_ATTACHMENT_FRONT_LEFT); + nconf->window_bit = TRUE; + nconf = &display->configs[display->num_configs++]; + nconf->color_format = formats[i]; + nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT; + nconf->pixmap_bit = TRUE; + } + } + + return TRUE; +} + +static boolean +directfb_display_init_screen( struct native_display *ndpy ) +{ + struct directfb_display *display = + directfb_display( ndpy ); + struct sw_winsys *ws; + + ws = directfb_sw_create(); + if (!ws) + return FALSE; + + display->base.screen = + display->event_handler->new_sw_screen( &display->base, ws ); + + if (!display->base.screen) { + if (ws->destroy) + ws->destroy( ws ); + return FALSE; + } + + if (!directfb_display_init_config( &display->base )) { + ndpy_uninit( &display->base ); + return FALSE; + } + + return TRUE; +} + +/** + * Update the geometry of the surface. This is a slow functions. + */ +static void +directfb_surface_update_geometry( struct native_surface *nsurf ) +{ + struct directfb_surface *surf = + directfb_surface( nsurf ); + int w, h; + + surf->pSurface->GetSize( surf->pSurface, &w, &h ); + if (resource_surface_set_size( surf->rsurf, w, h )) + surf->server_stamp++; +} + +/** + * Update the buffers of the surface. + */ +static boolean +directfb_surface_update_buffers( struct native_surface *nsurf, + uint buffer_mask ) +{ + struct directfb_surface *surf = + directfb_surface(nsurf); + + if (surf->client_stamp != surf->server_stamp) { + directfb_surface_update_geometry( &surf->base ); + surf->client_stamp = surf->server_stamp; + } + + return resource_surface_add_resources( surf->rsurf, buffer_mask ); +} + +/** + * Emulate an invalidate event. + */ +static void +directfb_surface_invalidate( struct native_surface *nsurf ) +{ + struct directfb_surface *surf = + directfb_surface( nsurf ); + struct directfb_display *display = + surf->display; + + surf->server_stamp++; + display->event_handler->invalid_surface( &display->base, + &surf->base, + surf->server_stamp ); +} + +static boolean +directfb_surface_flush_frontbuffer( struct native_surface *nsurf ) +{ + struct directfb_surface *surf = + directfb_surface( nsurf ); + boolean ret; + + ret = resource_surface_present( surf->rsurf, + NATIVE_ATTACHMENT_FRONT_LEFT, + (void *)surf->pSurface ); + + /* force buffers to be updated in next validation call */ + directfb_surface_invalidate( &surf->base ); + + return ret; +} + +static boolean +directfb_surface_swap_buffers( struct native_surface *nsurf ) +{ + struct directfb_surface *surf = + directfb_surface( nsurf ); + boolean ret; + + /* surf will be flipped in directfb_sw_displaytarget_display() */ + ret = resource_surface_present( surf->rsurf, + NATIVE_ATTACHMENT_BACK_LEFT, + (void *)surf->pSurface ); + + resource_surface_swap_buffers( surf->rsurf, + NATIVE_ATTACHMENT_FRONT_LEFT, + NATIVE_ATTACHMENT_BACK_LEFT, + TRUE ); + + /* the front/back buffers have been swapped */ + directfb_surface_invalidate( &surf->base ); + + return ret; +} + +static boolean +directfb_surface_present( struct native_surface *nsurf, + const struct native_present_control *ctrl ) +{ + boolean ret; + + if (ctrl->preserve || ctrl->swap_interval) + return FALSE; + + switch (ctrl->natt) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + ret = directfb_surface_flush_frontbuffer( nsurf ); + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + ret = directfb_surface_swap_buffers( nsurf ); + break; + default: + ret = FALSE; + break; + } + + return ret; +} + +static boolean +directfb_surface_validate( struct native_surface *nsurf, + uint attachment_mask, + unsigned int *seq_num, + struct pipe_resource **textures, + int *width, + int *height ) +{ + struct directfb_surface *surf = + directfb_surface( nsurf ); + uint w, h; + + if (!directfb_surface_update_buffers( &surf->base, attachment_mask )) + return FALSE; + + if (seq_num) + *seq_num = surf->client_stamp; + + if (textures) + resource_surface_get_resources( surf->rsurf, textures, attachment_mask ); + + resource_surface_get_size( surf->rsurf, &w, &h ); + if (width) + *width = w; + if (height) + *height = h; + + return TRUE; +} + +static void +directfb_surface_wait( struct native_surface *nsurf ) +{ + /* no-op */ +} + +static void +directfb_surface_destroy( struct native_surface *nsurf ) +{ + struct directfb_surface *surf = + directfb_surface( nsurf ); + + surf->pSurface->Release( surf->pSurface ); + resource_surface_destroy( surf->rsurf ); + FREE( surf ); +} + +static boolean +directfb_display_get_pixmap_format( struct native_display *ndpy, + EGLNativePixmapType pix, + enum pipe_format *format ) +{ + return false; +} + +static boolean +directfb_display_copy_to_pixmap( struct native_display *ndpy, + EGLNativePixmapType pix, + struct pipe_resource *src) +{ + /* for eglCopyBuffers() */ + return false; +} + +static bool +supported_pixelformat( DFBSurfacePixelFormat fmt ) +{ + switch (fmt) { + case DSPF_RGB16: + case DSPF_ARGB: + return true; + default: + return false; + } +} + +static DFBSurfacePixelFormat +dfb_pixelformat( enum pipe_format format ) +{ + switch (format) { + case PIPE_FORMAT_B5G6R5_UNORM: /* 16bit RGB */ + return DSPF_RGB16; + case PIPE_FORMAT_B8G8R8A8_UNORM: /* 32bit ARGB */ + return DSPF_ARGB; + default: + return DSPF_UNKNOWN; + } +} + +static struct native_surface* +directfb_display_create_pixmap_surface( struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf) +{ + struct directfb_display *display = + directfb_display( ndpy ); + struct directfb_surface *surf; + + DFBSurfaceCapabilities caps; + DFBSurfacePixelFormat fmt; + DFBResult ret; + + int w, h; + + IDirectFBSurface *pSurface = (IDirectFBSurface*)pix; + if (!pSurface) + return NULL; + + ret = pSurface->GetSize( pSurface, &w, &h ); + if (ret) + return NULL; + if (w <= 0 || h <= 0) + return NULL; + ret = pSurface->GetCapabilities( pSurface, &caps ); + if (ret) + return NULL; + if (caps & (DSCAPS_FLIPPING|DSCAPS_SUBSURFACE)) + return NULL; + pSurface->GetPixelFormat( pSurface, &fmt ); + if (!supported_pixelformat( fmt )) + return NULL; + if (dfb_pixelformat( nconf->color_format ) != fmt) + return NULL; + + surf = CALLOC_STRUCT( directfb_surface ); + if (!surf) + return NULL; + ret = pSurface->GetSubSurface( pSurface, NULL, &surf->pSurface ); + if (ret) { + FREE( surf ); + return NULL; + } + + /* store the parent surface in the directfb_display */ + display->pSurface = pSurface; + + surf->display = display; + surf->format = nconf->color_format; + surf->rsurf = resource_surface_create( display->base.screen, + surf->format, + PIPE_BIND_RENDER_TARGET + /* winsys will provide dedicated + storage for the resource rather + than letting llvmpipe allocate + from system memory */ + | PIPE_BIND_DISPLAY_TARGET ); + if (!surf->rsurf) { + FREE( surf ); + return NULL; + } + + directfb_surface_update_geometry( &surf->base ); + + surf->base.destroy = directfb_surface_destroy; + surf->base.present = directfb_surface_present; + surf->base.validate = directfb_surface_validate; + surf->base.wait = directfb_surface_wait; + + return &surf->base; +} + +static struct native_surface * +directfb_display_create_window_surface( struct native_display *ndpy, + EGLNativeWindowType win, + const struct native_config *nconf ) +{ + struct directfb_display *display = + directfb_display( ndpy ); + struct directfb_surface *surf; + + DFBSurfaceCapabilities caps; + DFBSurfacePixelFormat fmt; + DFBResult ret; + + int w, h; + + IDirectFBSurface *pSurface = (IDirectFBSurface*)win; + if (!pSurface) + return NULL; + + ret = pSurface->GetSize( pSurface, &w, &h ); + if (ret) + return NULL; + if (w <= 0 || h <= 0) + return NULL; + ret = pSurface->GetCapabilities( pSurface, &caps ); + if (ret) + return NULL; + if (!(caps & DSCAPS_FLIPPING) + || (caps & DSCAPS_SUBSURFACE)) + return NULL; + pSurface->GetPixelFormat( pSurface, &fmt ); + if (!supported_pixelformat( fmt )) + return NULL; + if (dfb_pixelformat( nconf->color_format ) != fmt) + return NULL; + + surf = CALLOC_STRUCT( directfb_surface ); + if (!surf) + return NULL; + ret = pSurface->GetSubSurface( pSurface, NULL, &surf->pSurface ); + if (ret) { + FREE( surf ); + return NULL; + } + + /* store the parent surface in the directfb_display */ + display->pSurface = pSurface; + + surf->display = display; + surf->format = nconf->color_format; + surf->rsurf = resource_surface_create( display->base.screen, + surf->format, + PIPE_BIND_RENDER_TARGET + | PIPE_BIND_DISPLAY_TARGET ); + if (!surf->rsurf) { + FREE( surf ); + return NULL; + } + + directfb_surface_update_geometry( &surf->base ); + + surf->base.destroy = directfb_surface_destroy; + surf->base.present = directfb_surface_present; + surf->base.validate = directfb_surface_validate; + surf->base.wait = directfb_surface_wait; + + return &surf->base; +} + +static struct native_display * +directfb_display_create( const struct native_event_handler *event_handler ) +{ + struct directfb_display *display; + + display = CALLOC_STRUCT( directfb_display ); + if (!display) + return NULL; + + display->event_handler = event_handler; + + display->base.init_screen = directfb_display_init_screen; + display->base.destroy = directfb_display_destroy; + display->base.get_param = directfb_display_get_param; + display->base.get_configs = directfb_display_get_configs; + display->base.get_pixmap_format = directfb_display_get_pixmap_format; + display->base.copy_to_pixmap = directfb_display_copy_to_pixmap; + display->base.create_pixmap_surface = + directfb_display_create_pixmap_surface; + display->base.create_window_surface = + directfb_display_create_window_surface; + + return &display->base; +} + +static const struct native_event_handler *directfb_event_handler; + +static struct native_display* +native_create_display( void *dpy, boolean use_sw ) +{ + struct native_display *display = + directfb_display_create( directfb_event_handler ); + return display; +} + +static const struct native_platform directfb_platform = { + "DirectFB", + native_create_display +}; + +const struct native_platform * +native_get_directfb_platform( const struct native_event_handler *event_handler ) +{ + directfb_event_handler = event_handler; + return &directfb_platform; +} -- 1.8.1.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev