diff options
author | David Reveman <davidr@novell.com> | 2005-05-19 13:30:49 +0000 |
---|---|---|
committer | David Reveman <davidr@novell.com> | 2005-05-19 13:30:49 +0000 |
commit | 43dcd2317802a79eee54eee7b1ae74bd1ccc5d69 (patch) | |
tree | 6ed2c396435fd1ecfa32b53a39805f99f948b5eb /src | |
parent | 65f551e0bb453a6d98225686485914f242296cfb (diff) |
Add EGL backend
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/egl/.cvsignore | 7 | ||||
-rw-r--r-- | src/egl/Makefile.am | 40 | ||||
-rw-r--r-- | src/egl/glitz-egl.h | 78 | ||||
-rw-r--r-- | src/egl/glitz-egl.man | 27 | ||||
-rw-r--r-- | src/egl/glitz-egl.pc.in | 11 | ||||
-rw-r--r-- | src/egl/glitz_egl_config.c | 221 | ||||
-rw-r--r-- | src/egl/glitz_egl_context.c | 357 | ||||
-rw-r--r-- | src/egl/glitz_egl_extension.c | 74 | ||||
-rw-r--r-- | src/egl/glitz_egl_info.c | 432 | ||||
-rw-r--r-- | src/egl/glitz_egl_pbuffer.c | 67 | ||||
-rw-r--r-- | src/egl/glitz_egl_surface.c | 203 | ||||
-rw-r--r-- | src/egl/glitz_eglext.h | 56 | ||||
-rw-r--r-- | src/egl/glitz_eglint.h | 171 |
14 files changed, 1745 insertions, 1 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index ffa75d7..43e1470 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = . glx agl +SUBDIRS = . glx agl egl lib_LTLIBRARIES = libglitz.la include_HEADERS = glitz.h diff --git a/src/egl/.cvsignore b/src/egl/.cvsignore new file mode 100644 index 0000000..6829f0d --- /dev/null +++ b/src/egl/.cvsignore @@ -0,0 +1,7 @@ +Makefile +Makefile.in +*.la +*.lo +*.loT +.libs +.deps diff --git a/src/egl/Makefile.am b/src/egl/Makefile.am new file mode 100644 index 0000000..547bb84 --- /dev/null +++ b/src/egl/Makefile.am @@ -0,0 +1,40 @@ +if GLITZ_BUILD_EGL_BACKEND + +INCLUDES = \ + $(GLITZ_INC) \ + $(EGL_CFLAGS) + +lib_LTLIBRARIES = libglitz-egl.la +include_HEADERS = glitz-egl.h + +libglitz_egl_la_SOURCES = \ + glitz-egl.h \ + glitz_egl_surface.c \ + glitz_egl_config.c \ + glitz_egl_info.c \ + glitz_egl_extension.c \ + glitz_egl_context.c \ + glitz_egl_pbuffer.c \ + glitz_eglext.h \ + glitz_eglint.h + +libglitz_egl_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined +libglitz_egl_la_LIBADD = $(GLITZ_LIB) $(EGL_LIBS) + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = glitz-egl.pc + +endif + +EXTRA_DIST = \ + glitz-egl.h \ + glitz_egl_surface.c \ + glitz_egl_config.c \ + glitz_egl_info.c \ + glitz_egl_extension.c \ + glitz_egl_context.c \ + glitz_egl_pbuffer.c \ + glitz_eglext.h \ + glitz_eglint.h \ + glitz-egl.pc.in \ + glitz-egl.man diff --git a/src/egl/glitz-egl.h b/src/egl/glitz-egl.h new file mode 100644 index 0000000..005732a --- /dev/null +++ b/src/egl/glitz-egl.h @@ -0,0 +1,78 @@ +/* + * Copyright © 2004 David Reveman + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * David Reveman not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * David Reveman makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <davidr@novell.com> + */ + +#ifndef GLITZ_EGL_H_INCLUDED +#define GLITZ_EGL_H_INCLUDED + +#include <GL/gl.h> +#include <GLES/egl.h> + +#include <glitz.h> + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +/* glitz_egl_info.c */ + +void +glitz_egl_init (const char *gl_library); + +void +glitz_egl_fini (void); + + +/* glitz_egl_config.c */ + +glitz_drawable_format_t * +glitz_egl_find_config (EGLDisplay egl_display, + EGLScreenMESA egl_screen, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count); + +/* glitz_egl_drawable.c */ + +glitz_drawable_t * +glitz_egl_create_window_surface (EGLDisplay display, + EGLScreenMESA screen, + glitz_drawable_format_t *format, + NativeWindowType window, + unsigned int width, + unsigned int height); + +glitz_drawable_t * +glitz_egl_create_pbuffer_surface (EGLDisplay display, + EGLScreenMESA screen, + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height); + + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* GLITZ_EGL_H_INCLUDED */ diff --git a/src/egl/glitz-egl.man b/src/egl/glitz-egl.man new file mode 100644 index 0000000..1387f41 --- /dev/null +++ b/src/egl/glitz-egl.man @@ -0,0 +1,27 @@ +.\" +.\" +.de TQ +.br +.ns +.TP +\\$1 +.. +.TH GLITZ-EGL 3 "Version 1.0" + +.SH NAME +GLITZ-EGL \- EGL interface to glitz + +.SH SYNOPSIS +.nf +.B #include <glitz-egl.h> +.fi +.SH DESCRIPTION + +EGL interface to glitz. + +.SH AUTHOR +David Reveman +Jon Smirl + +.SH "SEE ALSO" +.BR GLITZ (3) diff --git a/src/egl/glitz-egl.pc.in b/src/egl/glitz-egl.pc.in new file mode 100644 index 0000000..6182874 --- /dev/null +++ b/src/egl/glitz-egl.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libglitz-egl +Description: OpenGL compositing library (EGL backend) +Version: @VERSION@ +Requires: glitz +Libs: -L${libdir} -lglitz-egl @EGL_LIBS@ +Cflags: -I${includedir} @EGL_CFLAGS@ diff --git a/src/egl/glitz_egl_config.c b/src/egl/glitz_egl_config.c new file mode 100644 index 0000000..671c6d9 --- /dev/null +++ b/src/egl/glitz_egl_config.c @@ -0,0 +1,221 @@ +/* + * Copyright © 2004 David Reveman + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * David Reveman not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * David Reveman makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <davidr@novell.com> + */ + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#include "glitz_eglint.h" + +#include <stdlib.h> +#include <string.h> + +static int +_glitz_egl_format_compare (const void *elem1, + const void *elem2) +{ + int i, score[2]; + glitz_drawable_format_t *format[2]; + + format[0] = (glitz_drawable_format_t *) elem1; + format[1] = (glitz_drawable_format_t *) elem2; + i = score[0] = score[1] = 0; + + for (; i < 2; i++) { + if (format[i]->color.red_size) { + if (format[i]->color.red_size == 8) + score[i] += 5; + score[i] += 10; + } + + if (format[i]->color.green_size) { + if (format[i]->color.green_size == 8) + score[i] += 5; + score[i] += 10; + } + + if (format[i]->color.alpha_size) { + if (format[i]->color.alpha_size == 8) + score[i] += 5; + score[i] += 10; + } + + if (format[i]->stencil_size) + score[i] += 5; + + if (format[i]->depth_size) + score[i] += 5; + + if (format[i]->doublebuffer) + score[i] += 10; + + if (format[i]->types.window) + score[i] += 10; + + if (format[i]->types.pbuffer) + score[i] += 10; + + if (format[i]->samples > 1) + score[i] -= (20 - format[i]->samples); + } + + return score[1] - score[0]; +} + +static void +_glitz_add_format (glitz_egl_screen_info_t *screen_info, + glitz_drawable_format_t *format, + EGLConfig egl_id) +{ + if (!glitz_drawable_format_find (screen_info->formats, + screen_info->n_formats, + GLITZ_DRAWABLE_FORMAT_ALL_EXCEPT_ID_MASK, + format, 0)) { + int n = screen_info->n_formats; + + screen_info->formats = + realloc (screen_info->formats, + sizeof (glitz_drawable_format_t) * (n + 1)); + screen_info->egl_config_ids = + realloc (screen_info->egl_config_ids, sizeof (EGLConfig) * (n + 1)); + + if (screen_info->formats && screen_info->egl_config_ids) { + screen_info->formats[n] = *format; + screen_info->formats[n].id = n; + screen_info->egl_config_ids[n] = egl_id; + screen_info->n_formats++; + } + } +} + +static glitz_status_t +_glitz_egl_query_configs (glitz_egl_screen_info_t *screen_info) +{ + EGLDisplay egl_display; + glitz_drawable_format_t format; + EGLConfig *egl_configs; + int i, num_configs; + EGLConfig egl_id; + + egl_display = screen_info->display_info->egl_display; + + eglGetConfigs(egl_display, NULL, 0, &num_configs); + egl_configs = malloc(sizeof(*egl_configs) * num_configs); + eglGetConfigs(egl_display, egl_configs, num_configs, &num_configs); + + for (i = 0; i < num_configs; i++) { + int value; + + eglGetConfigAttrib(egl_display, egl_configs[i], + EGL_SURFACE_TYPE, &value); + if (!((value & EGL_WINDOW_BIT) || (value & EGL_PBUFFER_BIT))) + continue; + + format.types.window = (value & EGL_WINDOW_BIT)? 1: 0; + format.types.pbuffer = (value & EGL_PBUFFER_BIT)? 1: 0; + format.id = 0; + + eglGetConfigAttrib(egl_display, egl_configs[i], EGL_CONFIG_ID, &value); + egl_id = (EGLConfig) value; + + eglGetConfigAttrib(egl_display, egl_configs[i], EGL_RED_SIZE, &value); + format.color.red_size = (unsigned short) value; + eglGetConfigAttrib(egl_display, egl_configs[i], EGL_GREEN_SIZE, &value); + format.color.green_size = (unsigned short) value; + eglGetConfigAttrib(egl_display, egl_configs[i], EGL_BLUE_SIZE, &value); + format.color.blue_size = (unsigned short) value; + eglGetConfigAttrib(egl_display, egl_configs[i], EGL_ALPHA_SIZE, &value); + format.color.alpha_size = (unsigned short) value; + eglGetConfigAttrib(egl_display, egl_configs[i], EGL_DEPTH_SIZE, &value); + format.depth_size = (unsigned short) value; + eglGetConfigAttrib(egl_display, egl_configs[i], EGL_STENCIL_SIZE, &value); + format.stencil_size = (unsigned short) value; + + format.doublebuffer = 1; + + eglGetConfigAttrib(egl_display, egl_configs[i], EGL_SAMPLE_BUFFERS, &value); + if (value) { + eglGetConfigAttrib(egl_display, egl_configs[i], EGL_SAMPLES, &value); + format.samples = (unsigned short) (value > 1)? value: 1; + if (format.samples > 1) + format.types.pbuffer = 0; + } else + format.samples = 1; + + _glitz_add_format (screen_info, &format, egl_id); + } + + free(egl_configs); + + return GLITZ_STATUS_SUCCESS; +} + +void +glitz_egl_query_configs (glitz_egl_screen_info_t *screen_info) +{ + EGLConfig *egl_new_ids; + int i; + + _glitz_egl_query_configs (screen_info); + + if (!screen_info->n_formats) + return; + + qsort (screen_info->formats, screen_info->n_formats, + sizeof (glitz_drawable_format_t), _glitz_egl_format_compare); + + /* + * Update XID list so that it matches the sorted format list. + */ + egl_new_ids = malloc (sizeof (EGLConfig) * screen_info->n_formats); + if (!egl_new_ids) { + screen_info->n_formats = 0; + return; + } + + for (i = 0; i < screen_info->n_formats; i++) { + egl_new_ids[i] = screen_info->egl_config_ids[screen_info->formats[i].id]; + screen_info->formats[i].id = i; + } + + free (screen_info->egl_config_ids); + screen_info->egl_config_ids = egl_new_ids; +} + +glitz_drawable_format_t * +glitz_egl_find_config (EGLDisplay egl_display, + EGLScreenMESA egl_screen, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count) +{ + glitz_egl_screen_info_t *screen_info = + glitz_egl_screen_info_get (egl_display, egl_screen); + + return glitz_drawable_format_find (screen_info->formats, + screen_info->n_formats, + mask, templ, count); +} +slim_hidden_def(glitz_egl_find_config); diff --git a/src/egl/glitz_egl_context.c b/src/egl/glitz_egl_context.c new file mode 100644 index 0000000..89d77d3 --- /dev/null +++ b/src/egl/glitz_egl_context.c @@ -0,0 +1,357 @@ +/* + * Copyright © 2004 David Reveman + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * David Reveman not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * David Reveman makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <davidr@novell.com> + */ + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#include "glitz_eglint.h" + +#include <stdlib.h> + +extern glitz_gl_proc_address_list_t _glitz_egl_gl_proc_address; + +static void +_glitz_egl_context_create (glitz_egl_screen_info_t *screen_info, + EGLConfig egl_config, + EGLContext egl_share_list, + glitz_egl_context_t *context) +{ + context->id = egl_config; + context->egl_context = eglCreateContext (screen_info->display_info->egl_display, + egl_config, egl_share_list, NULL); +} + +static glitz_context_t * +_glitz_egl_create_context (void *abstract_drawable, + glitz_drawable_format_t *format) +{ + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable; + glitz_egl_screen_info_t *screen_info = drawable->screen_info; + int format_id = screen_info->egl_config_ids[format->id]; + glitz_egl_context_t *context; + + context = malloc (sizeof (glitz_egl_context_t)); + if (!context) + return NULL; + + _glitz_context_init (&context->base, &drawable->base); + + _glitz_egl_context_create (screen_info, + format_id, + screen_info->egl_root_context, + context); + + return (glitz_context_t *) context; +} + +static void +_glitz_egl_context_destroy (void *abstract_context) +{ + glitz_egl_context_t *context = (glitz_egl_context_t *) abstract_context; + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) + context->base.drawable; + + if (drawable->screen_info->display_info->thread_info->cctx == &context->base) + { + eglMakeCurrent (drawable->screen_info->display_info->egl_display, + EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + drawable->screen_info->display_info->thread_info->cctx = NULL; + } + + eglDestroyContext (drawable->screen_info->display_info->egl_display, + context->egl_context); + + _glitz_context_fini (&context->base); + + free (context); +} + +static void +_glitz_egl_copy_context (void *abstract_src, + void *abstract_dst, + unsigned long mask) +{ + glitz_egl_context_t *src = (glitz_egl_context_t *) abstract_src; + glitz_egl_context_t *dst = (glitz_egl_context_t *) abstract_dst; + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) + src->base.drawable; + + eglCopyContextMESA (drawable->screen_info->display_info->egl_display, + src->egl_context, dst->egl_context, mask); +} + +static void +_glitz_egl_make_current (void *abstract_context, + void *abstract_drawable) +{ + glitz_egl_context_t *context = (glitz_egl_context_t *) abstract_context; + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable; + glitz_egl_display_info_t *display_info = drawable->screen_info->display_info; + + if ((eglGetCurrentContext () != context->egl_context) || + (eglGetCurrentSurface ( 0 ) != drawable->egl_surface)) + eglMakeCurrent (display_info->egl_display, drawable->egl_surface, + drawable->egl_surface, context->egl_context); + + display_info->thread_info->cctx = &context->base; +} + +static glitz_function_pointer_t +_glitz_egl_context_get_proc_address (void *abstract_context, + const char *name) +{ + glitz_egl_context_t *context = (glitz_egl_context_t *) abstract_context; + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) + context->base.drawable; + + _glitz_egl_make_current (context, drawable); + + return glitz_egl_get_proc_address (name, drawable->screen_info); +} + +glitz_egl_context_t * +glitz_egl_context_get (glitz_egl_screen_info_t *screen_info, + glitz_drawable_format_t *format) +{ + glitz_egl_context_t *context; + glitz_egl_context_t **contexts = screen_info->contexts; + int index, n_contexts = screen_info->n_contexts; + EGLConfig egl_config_id; + + for (; n_contexts; n_contexts--, contexts++) + if ((*contexts)->id == screen_info->egl_config_ids[format->id]) + return *contexts; + + index = screen_info->n_contexts++; + + screen_info->contexts = + realloc (screen_info->contexts, + sizeof (glitz_egl_context_t *) * screen_info->n_contexts); + if (!screen_info->contexts) + return NULL; + + context = malloc (sizeof (glitz_egl_context_t)); + if (!context) + return NULL; + + screen_info->contexts[index] = context; + + egl_config_id = screen_info->egl_config_ids[format->id]; + + _glitz_egl_context_create (screen_info, + egl_config_id, + screen_info->egl_root_context, + context); + + if (!screen_info->egl_root_context) + screen_info->egl_root_context = context->egl_context; + + memcpy (&context->backend.gl, + &_glitz_egl_gl_proc_address, + sizeof (glitz_gl_proc_address_list_t)); + + context->backend.create_pbuffer = glitz_egl_create_pbuffer; + context->backend.destroy = glitz_egl_destroy; + context->backend.push_current = glitz_egl_push_current; + context->backend.pop_current = glitz_egl_pop_current; + context->backend.swap_buffers = glitz_egl_swap_buffers; + + context->backend.create_context = _glitz_egl_create_context; + context->backend.destroy_context = _glitz_egl_context_destroy; + context->backend.copy_context = _glitz_egl_copy_context; + context->backend.make_current = _glitz_egl_make_current; + context->backend.get_proc_address = _glitz_egl_context_get_proc_address; + + context->backend.drawable_formats = screen_info->formats; + context->backend.n_drawable_formats = screen_info->n_formats; + + context->backend.texture_formats = NULL; + context->backend.formats = NULL; + context->backend.n_formats = 0; + + context->backend.program_map = &screen_info->program_map; + context->backend.feature_mask = 0; + + context->initialized = 0; + + return context; +} + +void +glitz_egl_context_destroy (glitz_egl_screen_info_t *screen_info, + glitz_egl_context_t *context) +{ + if (context->backend.formats) + free (context->backend.formats); + + if (context->backend.texture_formats) + free (context->backend.texture_formats); + + eglDestroyContext (screen_info->display_info->egl_display, + context->egl_context); + free (context); +} + +static void +_glitz_egl_context_initialize (glitz_egl_screen_info_t *screen_info, + glitz_egl_context_t *context) +{ + const char *version; + + glitz_backend_init (&context->backend, + glitz_egl_get_proc_address, + (void *) screen_info); + + context->backend.gl.get_integer_v (GLITZ_GL_MAX_VIEWPORT_DIMS, + context->max_viewport_dims); + + glitz_initiate_state (&_glitz_egl_gl_proc_address); + + version = (const char *) context->backend.gl.get_string (GLITZ_GL_VERSION); + if (version) + { + /* Having trouble with TexSubImage2D to NPOT GL_TEXTURE_2D textures when + using nvidia's binary driver. Seems like a driver issue, but I'm not + sure yet. Turning of NPOT GL_TEXTURE_2D textures until this have been + solved. */ + if (strstr (version, "NVIDIA 61.11") || + strstr (version, "NVIDIA 66.29")) + { + context->backend.feature_mask &= + ~GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK; + } + } + + context->initialized = 1; +} + +static void +_glitz_egl_context_make_current (glitz_egl_surface_t *drawable, + glitz_bool_t finish) +{ + glitz_egl_display_info_t *display_info = drawable->screen_info->display_info; + + if (finish) + glFinish (); + + if (display_info->thread_info->cctx) + { + glitz_context_t *ctx = display_info->thread_info->cctx; + + if (ctx->lose_current) + ctx->lose_current (ctx->closure); + + display_info->thread_info->cctx = NULL; + } + + eglMakeCurrent (display_info->egl_display, + drawable->egl_surface, drawable->egl_surface, + drawable->context->egl_context); + + drawable->base.update_all = 1; + + if (!drawable->context->initialized) + _glitz_egl_context_initialize (drawable->screen_info, drawable->context); +} + +static void +_glitz_egl_context_update (glitz_egl_surface_t *drawable, + glitz_constraint_t constraint) +{ + EGLContext egl_context; + + switch (constraint) { + case GLITZ_NONE: + break; + case GLITZ_ANY_CONTEXT_CURRENT: { + glitz_egl_display_info_t *dinfo = drawable->screen_info->display_info; + + if (dinfo->thread_info->cctx) + { + _glitz_egl_context_make_current (drawable, 0); + } + else + { + egl_context = eglGetCurrentContext (); + if (egl_context == (EGLContext) 0) + _glitz_egl_context_make_current (drawable, 0); + } + } break; + case GLITZ_CONTEXT_CURRENT: + egl_context = eglGetCurrentContext (); + if (egl_context != drawable->context->egl_context) + _glitz_egl_context_make_current (drawable, (egl_context)? 1: 0); + break; + case GLITZ_DRAWABLE_CURRENT: + egl_context = eglGetCurrentContext (); + if ((egl_context != drawable->context->egl_context) || + (eglGetCurrentSurface ( 0 ) != drawable->egl_surface)) + _glitz_egl_context_make_current (drawable, (egl_context)? 1: 0); + break; + } +} + +void +glitz_egl_push_current (void *abstract_drawable, + glitz_surface_t *surface, + glitz_constraint_t constraint) +{ + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable; + glitz_egl_context_info_t *context_info; + int index; + + index = drawable->screen_info->context_stack_size++; + + context_info = &drawable->screen_info->context_stack[index]; + context_info->drawable = drawable; + context_info->surface = surface; + context_info->constraint = constraint; + + _glitz_egl_context_update (context_info->drawable, constraint); +} + +glitz_surface_t * +glitz_egl_pop_current (void *abstract_drawable) +{ + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable; + glitz_egl_context_info_t *context_info = NULL; + int index; + + drawable->screen_info->context_stack_size--; + index = drawable->screen_info->context_stack_size - 1; + + context_info = &drawable->screen_info->context_stack[index]; + + if (context_info->drawable) + _glitz_egl_context_update (context_info->drawable, + context_info->constraint); + + if (context_info->constraint == GLITZ_DRAWABLE_CURRENT) + return context_info->surface; + + return NULL; +} diff --git a/src/egl/glitz_egl_extension.c b/src/egl/glitz_egl_extension.c new file mode 100644 index 0000000..67ae1c0 --- /dev/null +++ b/src/egl/glitz_egl_extension.c @@ -0,0 +1,74 @@ +/* + * Copyright © 2004 David Reveman + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * David Reveman not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * David Reveman makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <davidr@novell.com> + */ + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#include "glitz_eglint.h" + +#if 0 +static glitz_extension_map egl_extensions[] = { + { 0.0, "EGL_SGIX_fbconfig", GLITZ_EGL_FEATURE_FBCONFIG_MASK }, + { 0.0, "EGL_SGIX_pbuffer", GLITZ_EGL_FEATURE_PBUFFER_MASK }, + { 0.0, "EGL_SGI_make_current_read", + GLITZ_EGL_FEATURE_MAKE_CURRENT_READ_MASK }, + { 0.0, "EGL_ARB_multisample", GLITZ_EGL_FEATURE_MULTISAMPLE_MASK }, + { 0.0, NULL, 0 } +}; +#endif + +void +glitz_egl_query_extensions (glitz_egl_screen_info_t *screen_info, + glitz_gl_float_t egl_version) +{ +#if 0 + const char *egl_extensions_string; + + egl_extensions_string = + eglQueryExtensionsString (screen_info->display_info->display, + screen_info->screen); + + screen_info->egl_feature_mask = + glitz_extensions_query (egl_version, + egl_extensions_string, + egl_extensions); + + if (screen_info->egl_feature_mask & GLITZ_EGL_FEATURE_MULTISAMPLE_MASK) { + const char *vendor; + + vendor = eglGetClientString (screen_info->display_info->display, + EGL_VENDOR); + + if (vendor) { + + /* NVIDIA's driver seem to support multisample with pbuffers */ + if (!strncmp ("NVIDIA", vendor, 6)) + screen_info->egl_feature_mask |= + GLITZ_EGL_FEATURE_PBUFFER_MULTISAMPLE_MASK; + } + } +#endif +} diff --git a/src/egl/glitz_egl_info.c b/src/egl/glitz_egl_info.c new file mode 100644 index 0000000..514de5c --- /dev/null +++ b/src/egl/glitz_egl_info.c @@ -0,0 +1,432 @@ +/* + * Copyright © 2004 David Reveman + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * David Reveman not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * David Reveman makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <davidr@novell.com> + */ + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#include "glitz_eglint.h" + +#include <pthread.h> +#include <string.h> +#include <dlfcn.h> + +glitz_gl_proc_address_list_t _glitz_egl_gl_proc_address = { + + /* core */ + (glitz_gl_enable_t) glEnable, + (glitz_gl_disable_t) glDisable, + (glitz_gl_get_error_t) glGetError, + (glitz_gl_get_string_t) glGetString, + (glitz_gl_enable_client_state_t) glEnableClientState, + (glitz_gl_disable_client_state_t) glDisableClientState, + (glitz_gl_vertex_pointer_t) glVertexPointer, + (glitz_gl_tex_coord_pointer_t) glTexCoordPointer, + (glitz_gl_draw_arrays_t) glDrawArrays, + (glitz_gl_tex_env_f_t) glTexEnvf, + (glitz_gl_tex_env_fv_t) glTexEnvfv, + (glitz_gl_tex_gen_i_t) glTexGeni, + (glitz_gl_tex_gen_fv_t) glTexGenfv, + (glitz_gl_color_4us_t) glColor4us, + (glitz_gl_color_4f_t) glColor4f, + (glitz_gl_scissor_t) glScissor, + (glitz_gl_blend_func_t) glBlendFunc, + (glitz_gl_clear_t) glClear, + (glitz_gl_clear_color_t) glClearColor, + (glitz_gl_clear_stencil_t) glClearStencil, + (glitz_gl_stencil_func_t) glStencilFunc, + (glitz_gl_stencil_op_t) glStencilOp, + (glitz_gl_push_attrib_t) glPushAttrib, + (glitz_gl_pop_attrib_t) glPopAttrib, + (glitz_gl_matrix_mode_t) glMatrixMode, + (glitz_gl_push_matrix_t) glPushMatrix, + (glitz_gl_pop_matrix_t) glPopMatrix, + (glitz_gl_load_identity_t) glLoadIdentity, + (glitz_gl_load_matrix_f_t) glLoadMatrixf, + (glitz_gl_depth_range_t) glDepthRange, + (glitz_gl_viewport_t) glViewport, + (glitz_gl_raster_pos_2f_t) glRasterPos2f, + (glitz_gl_bitmap_t) glBitmap, + (glitz_gl_read_buffer_t) glReadBuffer, + (glitz_gl_draw_buffer_t) glDrawBuffer, + (glitz_gl_copy_pixels_t) glCopyPixels, + (glitz_gl_flush_t) glFlush, + (glitz_gl_finish_t) glFinish, + (glitz_gl_pixel_store_i_t) glPixelStorei, + (glitz_gl_ortho_t) glOrtho, + (glitz_gl_scale_f_t) glScalef, + (glitz_gl_translate_f_t) glTranslatef, + (glitz_gl_hint_t) glHint, + (glitz_gl_depth_mask_t) glDepthMask, + (glitz_gl_polygon_mode_t) glPolygonMode, + (glitz_gl_shade_model_t) glShadeModel, + (glitz_gl_color_mask_t) glColorMask, + (glitz_gl_read_pixels_t) glReadPixels, + (glitz_gl_get_tex_image_t) glGetTexImage, + (glitz_gl_tex_sub_image_2d_t) glTexSubImage2D, + (glitz_gl_gen_textures_t) glGenTextures, + (glitz_gl_delete_textures_t) glDeleteTextures, + (glitz_gl_bind_texture_t) glBindTexture, + (glitz_gl_tex_image_2d_t) glTexImage2D, + (glitz_gl_tex_parameter_i_t) glTexParameteri, + (glitz_gl_get_tex_level_parameter_iv_t) glGetTexLevelParameteriv, + (glitz_gl_copy_tex_sub_image_2d_t) glCopyTexSubImage2D, + (glitz_gl_get_integer_v_t) glGetIntegerv, + + /* extensions */ + (glitz_gl_blend_color_t) 0, + (glitz_gl_active_texture_t) 0, + (glitz_gl_client_active_texture_t) 0, + (glitz_gl_multi_draw_arrays_t) 0, + (glitz_gl_gen_programs_t) 0, + (glitz_gl_delete_programs_t) 0, + (glitz_gl_program_string_t) 0, + (glitz_gl_bind_program_t) 0, + (glitz_gl_program_local_param_4fv_t) 0, + (glitz_gl_get_program_iv_t) 0, + (glitz_gl_gen_buffers_t) 0, + (glitz_gl_delete_buffers_t) 0, + (glitz_gl_bind_buffer_t) 0, + (glitz_gl_buffer_data_t) 0, + (glitz_gl_buffer_sub_data_t) 0, + (glitz_gl_get_buffer_sub_data_t) 0, + (glitz_gl_map_buffer_t) 0, + (glitz_gl_unmap_buffer_t) 0 +}; + +glitz_function_pointer_t +glitz_egl_get_proc_address (const char *name, + void *closure) +{ + glitz_egl_screen_info_t *screen_info = (glitz_egl_screen_info_t *) closure; + glitz_egl_thread_info_t *info = screen_info->display_info->thread_info; + glitz_function_pointer_t address = NULL; + + if (screen_info->egl_feature_mask & GLITZ_EGL_FEATURE_GET_PROC_ADDRESS_MASK) + address = eglGetProcAddress ((glitz_gl_ubyte_t *) name); + + if (!address) { + if (!info->dlhand) + info->dlhand = dlopen (info->gl_library, RTLD_LAZY); + + if (info->dlhand) { + dlerror (); + address = (glitz_function_pointer_t) dlsym (info->dlhand, name); + if (dlerror () != NULL) + address = NULL; + } + } + + return address; +} + +static void +_glitz_egl_display_destroy (glitz_egl_display_info_t *display_info); + +static void +_glitz_egl_screen_destroy (glitz_egl_screen_info_t *screen_info); + +static void +_glitz_egl_thread_info_fini (glitz_egl_thread_info_t *thread_info) +{ + int i; + + for (i = 0; i < thread_info->n_displays; i++) + _glitz_egl_display_destroy (thread_info->displays[i]); + + free (thread_info->displays); + + thread_info->displays = NULL; + thread_info->n_displays = 0; + + if (thread_info->gl_library) { + free (thread_info->gl_library); + thread_info->gl_library = NULL; + } + + if (thread_info->dlhand) { + dlclose (thread_info->dlhand); + thread_info->dlhand = NULL; + } + + thread_info->cctx = NULL; +} +#define PTHREADS +#ifdef PTHREADS + +/* thread safe */ +static int tsd_initialized = 0; +static pthread_key_t info_tsd; + +static void +_glitz_egl_thread_info_init (glitz_egl_thread_info_t *thread_info) +{ + thread_info->displays = NULL; + thread_info->n_displays = 0; + thread_info->gl_library = NULL; + thread_info->dlhand = NULL; + thread_info->cctx = NULL; +} + +static void +_glitz_egl_thread_info_destroy (glitz_egl_thread_info_t *thread_info) +{ + pthread_setspecific (info_tsd, NULL); + + if (thread_info) { + _glitz_egl_thread_info_fini (thread_info); + free (thread_info); + } +} + +static void +_tsd_destroy (void *p) +{ + if (p) { + _glitz_egl_thread_info_fini ((glitz_egl_thread_info_t *) p); + free (p); + } +} + +static glitz_egl_thread_info_t * +_glitz_egl_thread_info_get (const char *gl_library) +{ + glitz_egl_thread_info_t *thread_info; + void *p; + + if (!tsd_initialized) { + pthread_key_create (&info_tsd, _tsd_destroy); + tsd_initialized = 1; + } + + p = pthread_getspecific (info_tsd); + + if (p == NULL) { + thread_info = malloc (sizeof (glitz_egl_thread_info_t)); + _glitz_egl_thread_info_init (thread_info); + + pthread_setspecific (info_tsd, thread_info); + } else + thread_info = (glitz_egl_thread_info_t *) p; + + if (gl_library) { + int len = strlen (gl_library); + + if (thread_info->gl_library) { + free (thread_info->gl_library); + thread_info->gl_library = NULL; + } + + thread_info->gl_library = malloc (len + 1); + if (thread_info->gl_library) { + memcpy (thread_info->gl_library, gl_library, len); + thread_info->gl_library[len] = '\0'; + } + } + + return thread_info; +} + +#else + +/* not thread safe */ +static glitz_egl_thread_info_t thread_info = { + NULL, + 0, + NULL, + NULL +}; + +static void +_glitz_egl_thread_info_destroy (glitz_egl_thread_info_t *thread_info) +{ + if (thread_info) + _glitz_egl_thread_info_fini (thread_info); +} + +static glitz_egl_thread_info_t * +_glitz_egl_thread_info_get (const char *gl_library) +{ + if (gl_library) { + int len = strlen (gl_library); + + if (thread_info.gl_library) { + free (thread_info.gl_library); + thread_info.gl_library = NULL; + } + + thread_info.gl_library = malloc (len + 1); + if (thread_info.gl_library) { + memcpy (thread_info.gl_library, gl_library, len); + thread_info.gl_library[len] = '\0'; + } + } + + return &thread_info; +} + +#endif + +static glitz_egl_display_info_t * +_glitz_egl_display_info_get (EGLDisplay egl_display) +{ + glitz_egl_display_info_t *display_info; + glitz_egl_thread_info_t *thread_info = _glitz_egl_thread_info_get (NULL); + glitz_egl_display_info_t **displays = thread_info->displays; + int index, n_displays = thread_info->n_displays; + + for (; n_displays; n_displays--, displays++) + if ((*displays)->egl_display == egl_display) + return *displays; + + index = thread_info->n_displays++; + + thread_info->displays = + realloc (thread_info->displays, + sizeof (glitz_egl_display_info_t *) * thread_info->n_displays); + + display_info = malloc (sizeof (glitz_egl_display_info_t)); + thread_info->displays[index] = display_info; + + display_info->thread_info = thread_info; + display_info->egl_display = egl_display; + display_info->screens = NULL; + display_info->n_screens = 0; + + return display_info; +} + +static void +_glitz_egl_display_destroy (glitz_egl_display_info_t *display_info) +{ + int i; + + for (i = 0; i < display_info->n_screens; i++) + _glitz_egl_screen_destroy (display_info->screens[i]); + + if (display_info->screens) + free (display_info->screens); + + free (display_info); +} + +glitz_egl_screen_info_t * +glitz_egl_screen_info_get (EGLDisplay display, + EGLScreenMESA screen) +{ + glitz_egl_screen_info_t *screen_info; + glitz_egl_display_info_t *display_info = + _glitz_egl_display_info_get (display); + glitz_egl_screen_info_t **screens = display_info->screens; + int index, n_screens = display_info->n_screens; +#if 0 + int error_base, event_base; +#endif + + for (; n_screens; n_screens--, screens++) + if ((*screens)->screen == screen) + return *screens; + + index = display_info->n_screens++; + + display_info->screens = + realloc (display_info->screens, + sizeof (glitz_egl_screen_info_t *) * display_info->n_screens); + + screen_info = malloc (sizeof (glitz_egl_screen_info_t)); + display_info->screens[index] = screen_info; + + screen_info->display_info = display_info; + screen_info->screen = screen; + screen_info->drawables = 0; + screen_info->formats = NULL; + screen_info->egl_config_ids = NULL; + screen_info->n_formats = 0; + + screen_info->contexts = NULL; + screen_info->n_contexts = 0; + + glitz_program_map_init (&screen_info->program_map); + + screen_info->egl_root_context = (EGLContext) 0; + screen_info->egl_feature_mask = 0; +#if 0 + if (eglQueryExtension (display, &error_base, &event_base)) { + int major, minor; + + if (eglQueryVersion (display, &major, &minor)) { + screen_info->egl_version = major + minor / 10.0f; + if (major > 1 || (major > 0 || minor >= 2)) { + glitz_egl_query_extensions (screen_info, screen_info->egl_version); + _glitz_egl_proc_address_lookup (screen_info); + glitz_egl_query_formats (screen_info); + } + } + } +#endif + glitz_egl_query_extensions (screen_info, screen_info->egl_version); + glitz_egl_query_configs (screen_info); + + screen_info->context_stack_size = 1; + screen_info->context_stack->drawable = NULL; + screen_info->context_stack->surface = NULL; + screen_info->context_stack->constraint = GLITZ_NONE; + + return screen_info; +} + +static void +_glitz_egl_screen_destroy (glitz_egl_screen_info_t *screen_info) +{ + EGLDisplay egl_display = screen_info->display_info->egl_display; + int i; + + if (screen_info->egl_root_context) + eglMakeCurrent (egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + for (i = 0; i < screen_info->n_contexts; i++) + glitz_egl_context_destroy (screen_info, screen_info->contexts[i]); + + free (screen_info->contexts); + free (screen_info->formats); + free (screen_info->egl_config_ids); + free (screen_info); +} + +void +glitz_egl_init (const char *gl_library) +{ + _glitz_egl_thread_info_get (gl_library); +} +slim_hidden_def(glitz_egl_init); + +void +glitz_egl_fini (void) +{ + glitz_egl_thread_info_t *info = _glitz_egl_thread_info_get (NULL); + + _glitz_egl_thread_info_destroy (info); +} +slim_hidden_def(glitz_egl_fini); diff --git a/src/egl/glitz_egl_pbuffer.c b/src/egl/glitz_egl_pbuffer.c new file mode 100644 index 0000000..cfe147a --- /dev/null +++ b/src/egl/glitz_egl_pbuffer.c @@ -0,0 +1,67 @@ +/* + * Copyright © 2004 David Reveman + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * David Reveman not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * David Reveman makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <davidr@novell.com> + */ + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#include "glitz_eglint.h" + +EGLSurface +glitz_egl_pbuffer_create (glitz_egl_screen_info_t *screen_info, + EGLConfig egl_config, + int width, + int height) +{ + if (egl_config) { + int attributes[9]; + + attributes[0] = EGL_WIDTH; + attributes[1] = width; + + attributes[2] = EGL_HEIGHT; + attributes[3] = height; +#if 0 + attributes[4] = EGL_LARGEST_PBUFFER; + attributes[5] = 0; + + attributes[6] = EGL_PRESERVED_CONTENTS; + attributes[7] = 1; + attributes[8] = 0; +#endif + return + eglCreatePbufferSurface(screen_info->display_info->egl_display, + egl_config, attributes); + } else + return (EGLSurface) 0; +} + +void +glitz_egl_pbuffer_destroy (glitz_egl_screen_info_t *screen_info, + EGLSurface egl_pbuffer) +{ + eglDestroySurface(screen_info->display_info->egl_display, + egl_pbuffer); +} diff --git a/src/egl/glitz_egl_surface.c b/src/egl/glitz_egl_surface.c new file mode 100644 index 0000000..4afdd7a --- /dev/null +++ b/src/egl/glitz_egl_surface.c @@ -0,0 +1,203 @@ +/* + * Copyright © 2004 David Reveman + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * David Reveman not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * David Reveman makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <davidr@novell.com> + */ + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif + +#include "glitz_eglint.h" + +static glitz_egl_surface_t * +_glitz_egl_create_surface (glitz_egl_screen_info_t *screen_info, + glitz_egl_context_t *context, + glitz_drawable_format_t *format, + EGLSurface egl_surface, + int width, + int height) +{ + glitz_egl_surface_t *surface; + + if (width <= 0 || height <= 0) + return NULL; + + surface = (glitz_egl_surface_t *) malloc (sizeof (glitz_egl_surface_t)); + if (surface == NULL) + return NULL; + + surface->base.ref_count = 1; + surface->screen_info = screen_info; + surface->context = context; + surface->egl_surface = egl_surface; + surface->base.format = format; + surface->base.backend = &context->backend; + + glitz_drawable_update_size (&surface->base, width, height); + + if (!context->initialized) { + glitz_egl_push_current (surface, NULL, GLITZ_CONTEXT_CURRENT); + glitz_egl_pop_current (surface); + } + + if (width > context->max_viewport_dims[0] || + height > context->max_viewport_dims[1]) { + free (surface); + return NULL; + } + + screen_info->drawables++; + + return surface; +} + +static glitz_drawable_t * +_glitz_egl_create_pbuffer_surface (glitz_egl_screen_info_t *screen_info, + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height) +{ + glitz_egl_surface_t *surface; + glitz_egl_context_t *context; + EGLSurface egl_pbuffer; + + if (!format->types.pbuffer) + return NULL; + + context = glitz_egl_context_get (screen_info, format); + if (!context) + return NULL; + + egl_pbuffer = glitz_egl_pbuffer_create (screen_info, context->egl_config, + (int) width, (int) height); + if (!egl_pbuffer) + return NULL; + + surface = _glitz_egl_create_surface (screen_info, context, format, + egl_pbuffer, + width, height); + if (!surface) { + glitz_egl_pbuffer_destroy (screen_info, egl_pbuffer); + return NULL; + } + + return &surface->base; +} + +glitz_drawable_t * +glitz_egl_create_pbuffer (void *abstract_templ, + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height) +{ + glitz_egl_surface_t *templ = (glitz_egl_surface_t *) abstract_templ; + + return _glitz_egl_create_pbuffer_surface (templ->screen_info, format, + width, height); +} + +glitz_drawable_t * +glitz_egl_create_window_surface (EGLDisplay display, + EGLScreenMESA screen, + glitz_drawable_format_t *format, + NativeWindowType window, + unsigned int width, + unsigned int height) +{ + glitz_egl_surface_t *surface; + glitz_egl_screen_info_t *screen_info; + glitz_egl_context_t *context; + + screen_info = glitz_egl_screen_info_get (display, screen); + if (!screen_info) + return NULL; + + context = glitz_egl_context_get (screen_info, format); + if (!context) + return NULL; + + surface = _glitz_egl_create_surface (screen_info, context, format, + window, + width, height); + if (!surface) + return NULL; + + return &surface->base; +} +slim_hidden_def(glitz_egl_create_window_surface); + +glitz_drawable_t * +glitz_egl_create_pbuffer_surface (EGLDisplay display, + EGLScreenMESA screen, + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height) +{ + glitz_egl_screen_info_t *screen_info; + + screen_info = glitz_egl_screen_info_get (display, screen); + if (!screen_info) + return NULL; + + return _glitz_egl_create_pbuffer_surface (screen_info, format, + width, height); +} +slim_hidden_def(glitz_egl_create_pbuffer_surface); + +void +glitz_egl_destroy (void *abstract_drawable) +{ + EGLint value; + glitz_egl_surface_t *surface = (glitz_egl_surface_t *) abstract_drawable; + + surface->screen_info->drawables--; + if (surface->screen_info->drawables == 0) { + /* + * Last drawable? We have to destroy all fragment programs as this may + * be our last chance to have a context current. + */ + glitz_egl_push_current (abstract_drawable, NULL, GLITZ_CONTEXT_CURRENT); + glitz_program_map_fini (&surface->base.backend->gl, + &surface->screen_info->program_map); + glitz_egl_pop_current (abstract_drawable); + } + + if (eglGetCurrentSurface ( 0 ) == surface->egl_surface) + eglMakeCurrent (surface->screen_info->display_info->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + eglQuerySurface (surface->screen_info->display_info->egl_display, surface->egl_surface, + EGL_SURFACE_TYPE, &value); + if (value == EGL_PBUFFER_BIT) + glitz_egl_pbuffer_destroy (surface->screen_info, surface->egl_surface); + + free (surface); +} + +void +glitz_egl_swap_buffers (void *abstract_drawable) +{ + glitz_egl_surface_t *surface = (glitz_egl_surface_t *) abstract_drawable; + + eglSwapBuffers (surface->screen_info->display_info->egl_display, + surface->egl_surface); +} diff --git a/src/egl/glitz_eglext.h b/src/egl/glitz_eglext.h new file mode 100644 index 0000000..49c2721 --- /dev/null +++ b/src/egl/glitz_eglext.h @@ -0,0 +1,56 @@ +/* + * Copyright © 2004 David Reveman, Peter Nilsson + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the names of + * David Reveman and Peter Nilsson not be used in advertising or + * publicity pertaining to distribution of the software without + * specific, written prior permission. David Reveman and Peter Nilsson + * makes no representations about the suitability of this software for + * any purpose. It is provided "as is" without express or implied warranty. + * + * DAVID REVEMAN AND PETER NILSSON DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DAVID REVEMAN AND + * PETER NILSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA + * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: David Reveman <davidr@novell.com> + * Peter Nilsson <c99pnn@cs.umu.se> + */ + +#ifndef GLITZ_EGLEXT_H_INCLUDED +#define GLITZ_EGLEXT_H_INCLUDED + + +typedef glitz_function_pointer_t (* glitz_egl_get_proc_address_t) + (const glitz_gl_ubyte_t *); +typedef EGLConfig *(* glitz_egl_get_configs_t) + (EGLDisplay egl_display, EGLScreenMESA egl_screen, int *n_elements); +typedef int (* glitz_egl_get_config_attrib_t) + (EGLDisplay egl_display, EGLConfig egl_config, int attribute, int *value); +typedef EGLSurface (* glitz_egl_create_pbuffer_t) + (EGLDisplay egl_display, EGLConfig egl_config, const int *attrib_list); +typedef void (* glitz_egl_destroy_pbuffer_t) + (EGLDisplay egl_display, EGLSurface egl_pbuffer); +typedef void (* glitz_egl_query_drawable_t) + (EGLDisplay egl_display, EGLSurface egl_surface, + int attribute, unsigned int *value); +typedef EGLBoolean (* glitz_egl_make_context_current_t) + (EGLDisplay egl_display, EGLSurface egl_draw, EGLSurface egl_read, EGLContext egl_ctx); +typedef EGLContext (* glitz_egl_create_new_context_t) + (EGLDisplay egl_display, EGLConfig egl_config, int render_type, + EGLContext egl_share_list, EGLBoolean direct); + +typedef EGLBoolean *(* glitz_egl_bind_tex_image_t) + (EGLDisplay egl_display, EGLSurface egl_pbuffer, int buffer); +typedef EGLBoolean (* glitz_egl_release_tex_image_t) + (EGLDisplay egl_display, EGLSurface egl_pbuffer, int buffer); + +#endif /* GLITZ_EGLEXT_H_INCLUDED */ diff --git a/src/egl/glitz_eglint.h b/src/egl/glitz_eglint.h new file mode 100644 index 0000000..7a61488 --- /dev/null +++ b/src/egl/glitz_eglint.h @@ -0,0 +1,171 @@ +/* + * Copyright © 2004 David Reveman + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * David Reveman not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * David Reveman makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <davidr@novell.com> + */ + +#ifndef GLITZ_EGLINT_H_INCLUDED +#define GLITZ_EGLINT_H_INCLUDED + +#include "glitz.h" +#include "glitzint.h" + +#include "glitz-egl.h" + +#include "glitz_eglext.h" + +#define GLITZ_EGL_FEATURE_MAKE_CURRENT_READ_MASK (1L << 2) +#define GLITZ_EGL_FEATURE_GET_PROC_ADDRESS_MASK (1L << 3) +#define GLITZ_EGL_FEATURE_MULTISAMPLE_MASK (1L << 4) +#define GLITZ_EGL_FEATURE_PBUFFER_MULTISAMPLE_MASK (1L << 5) + +typedef struct _glitz_egl_surface glitz_egl_surface_t; +typedef struct _glitz_egl_screen_info_t glitz_egl_screen_info_t; +typedef struct _glitz_egl_display_info_t glitz_egl_display_info_t; + +typedef struct _glitz_egl_thread_info_t { + glitz_egl_display_info_t **displays; + int n_displays; + char *gl_library; + void *dlhand; + glitz_context_t *cctx; +} glitz_egl_thread_info_t; + +struct _glitz_egl_display_info_t { + glitz_egl_thread_info_t *thread_info; + EGLDisplay egl_display; + glitz_egl_screen_info_t **screens; + int n_screens; +}; + +typedef struct _glitz_egl_context_info_t { + glitz_egl_surface_t *drawable; + glitz_surface_t *surface; + glitz_constraint_t constraint; +} glitz_egl_context_info_t; + +typedef struct _glitz_egl_context_t { + glitz_context_t base; + EGLContext egl_context; + glitz_format_id_t id; + EGLConfig egl_config; + glitz_backend_t backend; + glitz_gl_int_t max_viewport_dims[2]; + glitz_gl_int_t max_texture_2d_size; + glitz_gl_int_t max_texture_rect_size; + glitz_bool_t initialized; +} glitz_egl_context_t; + +struct _glitz_egl_screen_info_t { + glitz_egl_display_info_t *display_info; + int screen; + int drawables; + glitz_drawable_format_t *formats; + EGLConfig *egl_config_ids; + int n_formats; + glitz_egl_context_t **contexts; + int n_contexts; + glitz_egl_context_info_t context_stack[GLITZ_CONTEXT_STACK_SIZE]; + int context_stack_size; + EGLContext egl_root_context; + unsigned long egl_feature_mask; + glitz_gl_float_t egl_version; + glitz_program_map_t program_map; +}; + +struct _glitz_egl_surface { + glitz_drawable_t base; + + glitz_egl_screen_info_t *screen_info; + glitz_egl_context_t *context; + EGLSurface egl_surface; +}; + +extern void __internal_linkage +glitz_egl_query_extensions (glitz_egl_screen_info_t *screen_info, + glitz_gl_float_t egl_version); + +extern glitz_egl_screen_info_t __internal_linkage * +glitz_egl_screen_info_get (EGLDisplay egl_display, + EGLScreenMESA egl_screen); + +extern glitz_function_pointer_t __internal_linkage +glitz_egl_get_proc_address (const char *name, + void *closure); + +extern glitz_egl_context_t __internal_linkage * +glitz_egl_context_get (glitz_egl_screen_info_t *screen_info, + glitz_drawable_format_t *format); + +extern void __internal_linkage +glitz_egl_context_destroy (glitz_egl_screen_info_t *screen_info, + glitz_egl_context_t *context); + +extern void __internal_linkage +glitz_egl_query_configs (glitz_egl_screen_info_t *screen_info); + +extern EGLSurface __internal_linkage +glitz_egl_pbuffer_create (glitz_egl_screen_info_t *screen_info, + EGLConfig egl_config, + int width, + int height); + +extern void __internal_linkage +glitz_egl_pbuffer_destroy (glitz_egl_screen_info_t *screen_info, + EGLSurface egl_pbuffer); + +extern glitz_drawable_t __internal_linkage * +glitz_egl_create_pbuffer (void *abstract_templ, + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height); + +extern void __internal_linkage +glitz_egl_push_current (void *abstract_drawable, + glitz_surface_t *surface, + glitz_constraint_t constraint); + +extern glitz_surface_t __internal_linkage * +glitz_egl_pop_current (void *abstract_drawable); + +void +glitz_egl_make_current (void *abstract_drawable, + glitz_constraint_t constraint); + +extern glitz_status_t __internal_linkage +glitz_egl_make_current_read (void *abstract_surface); + +extern void __internal_linkage +glitz_egl_destroy (void *abstract_drawable); + +extern void __internal_linkage +glitz_egl_swap_buffers (void *abstract_drawable); + +/* Avoid unnecessary PLT entries. */ + +slim_hidden_proto(glitz_egl_init) +slim_hidden_proto(glitz_egl_fini) +slim_hidden_proto(glitz_egl_find_config) +slim_hidden_proto(glitz_egl_create_window_surface) +slim_hidden_proto(glitz_egl_create_pbuffer_surface) + +#endif /* GLITZ_EGLINT_H_INCLUDED */ |