summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChia-I Wu <olvaffe@gmail.com>2010-02-04 10:55:33 +0800
committerChia-I Wu <olvaffe@gmail.com>2010-02-04 10:55:33 +0800
commitfcceafbcb67f97264d3e880ac4389770a2799454 (patch)
treee03181d5c374ef18d74aa68c7e1a5f4e399ff409
parent7d56fc70b15ff52658a3e6c416f5c1699a8b670c (diff)
Add a sample implementation.
-rw-r--r--sample-implementation-tmp/0001-gallium-Add-st_api.h.patch420
-rw-r--r--sample-implementation-tmp/0002-gallium-Suffix-st_framebuffer-and-st_context-with-_i.patch175
-rw-r--r--sample-implementation-tmp/0003-st-vega-Implement-st_api-interface.patch504
-rw-r--r--sample-implementation-tmp/0004-st-egl-Add-support-for-loading-st_api-modules.patch189
-rw-r--r--sample-implementation-tmp/0005-st-egl-Use-st_api.h-instead-of-st_public.h.patch1103
5 files changed, 2391 insertions, 0 deletions
diff --git a/sample-implementation-tmp/0001-gallium-Add-st_api.h.patch b/sample-implementation-tmp/0001-gallium-Add-st_api.h.patch
new file mode 100644
index 0000000..98f1372
--- /dev/null
+++ b/sample-implementation-tmp/0001-gallium-Add-st_api.h.patch
@@ -0,0 +1,420 @@
+From 94e420c2b04c3e14a920106d117a94aaf74404b2 Mon Sep 17 00:00:00 2001
+From: Chia-I Wu <olvaffe@gmail.com>
+Date: Wed, 13 Jan 2010 17:57:35 +0800
+Subject: [PATCH 1/5] gallium: Add st_api.h.
+
+---
+ src/gallium/include/state_tracker/st_api.h | 401 ++++++++++++++++++++++++++++
+ 1 files changed, 401 insertions(+), 0 deletions(-)
+ create mode 100644 src/gallium/include/state_tracker/st_api.h
+
+diff --git a/src/gallium/include/state_tracker/st_api.h b/src/gallium/include/state_tracker/st_api.h
+new file mode 100644
+index 0000000..8feaade
+--- /dev/null
++++ b/src/gallium/include/state_tracker/st_api.h
+@@ -0,0 +1,401 @@
++/**********************************************************
++ * Copyright 2010 VMware, Inc. All rights reserved.
++ *
++ * 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.
++ *
++ **********************************************************/
++
++
++#ifndef _ST_API_H_
++#define _ST_API_H_
++
++#include "pipe/p_compiler.h"
++#include "pipe/p_format.h"
++
++/**
++ * \file API for communication between state trackers and state tracker
++ * managers.
++ *
++ * While both are state tackers, we use the term state tracker for rendering
++ * APIs such as OpenGL or OpenVG, and state tracker manager for window system
++ * APIs such as EGL or GLX in this file.
++ *
++ * This file defines an API to be implemented by both state trackers and state
++ * tracker managers.
++ */
++
++/**
++ * The entry points of the state trackers.
++ */
++#define ST_MODULE_OPENGL_SYMBOL "st_module_OpenGL"
++#define ST_MODULE_OPENGL_ES1_SYMBOL "st_module_OpenGL_ES1"
++#define ST_MODULE_OPENGL_ES2_SYMBOL "st_module_OpenGL_ES2"
++#define ST_MODULE_OPENVG_SYMBOL "st_module_OpenVG"
++
++/**
++ * The supported rendering API of a state tracker.
++ */
++enum st_api_type {
++ ST_API_OPENGL,
++ ST_API_OPENGL_ES1,
++ ST_API_OPENGL_ES2,
++ ST_API_OPENVG,
++
++ ST_API_COUNT
++};
++
++/**
++ * Used in st_context->teximage.
++ */
++enum st_texture_type {
++ ST_TEXTURE_1D,
++ ST_TEXTURE_2D,
++ ST_TEXTURE_3D,
++ ST_TEXTURE_RECT,
++};
++
++/**
++ * Available attachments of framebuffer.
++ */
++enum st_attachment_type {
++ ST_ATTACHMENT_FRONT_LEFT,
++ ST_ATTACHMENT_BACK_LEFT,
++ ST_ATTACHMENT_FRONT_RIGHT,
++ ST_ATTACHMENT_BACK_RIGHT,
++ ST_ATTACHMENT_DEPTH_STENCIL,
++ ST_ATTACHMENT_ACCUM,
++ ST_ATTACHMENT_SAMPLE,
++
++ ST_ATTACHMENT_COUNT,
++ ST_ATTACHMENT_INVALID = -1
++};
++
++/* for buffer_mask in st_visual */
++#define ST_ATTACHMENT_FRONT_LEFT_MASK (1 << ST_ATTACHMENT_FRONT_LEFT)
++#define ST_ATTACHMENT_BACK_LEFT_MASK (1 << ST_ATTACHMENT_BACK_LEFT)
++#define ST_ATTACHMENT_FRONT_RIGHT_MASK (1 << ST_ATTACHMENT_FRONT_RIGHT)
++#define ST_ATTACHMENT_BACK_RIGHT_MASK (1 << ST_ATTACHMENT_BACK_RIGHT)
++#define ST_ATTACHMENT_DEPTH_STENCIL_MASK (1 << ST_ATTACHMENT_DEPTH_STENCIL)
++#define ST_ATTACHMENT_ACCUM_MASK (1 << ST_ATTACHMENT_ACCUM)
++#define ST_ATTACHMENT_SAMPLE_MASK (1 << ST_ATTACHMENT_SAMPLE)
++
++/**
++ * Enumerations of state tracker manager resources.
++ */
++enum st_manager_resource_type {
++ /* return struct pipe_surface (this is likely to change) */
++ ST_MANAGER_RESOURCE_EGL_IMAGE,
++};
++
++/**
++ * Enumerations of state tracker context resources.
++ */
++enum st_context_resource_type {
++ /* all of them return struct pipe_texture */
++ ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_2D,
++ ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_3D,
++ ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_X,
++ ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_X,
++ ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Y,
++ ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
++ ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Z,
++ ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
++ ST_CONTEXT_RESOURCE_OPENGL_RENDERBUFFER,
++ ST_CONTEXT_RESOURCE_OPENVG_PARENT_IMAGE,
++};
++
++/**
++ * The return type of st_api->get_proc_address.
++ */
++typedef void (*st_proc_t)(void);
++
++struct pipe_context;
++struct pipe_texture;
++struct pipe_fence_handle;
++
++/**
++ * Represent the visual of a framebuffer.
++ */
++struct st_visual
++{
++ /**
++ * Available buffers. Tested with ST_FRAMEBUFFER_*_MASK.
++ */
++ unsigned buffer_mask;
++
++ /**
++ * Buffer formats. The formats are always set even when the buffer is
++ * not available.
++ */
++ enum pipe_format color_format;
++ enum pipe_format depth_stencil_format;
++ enum pipe_format accum_format;
++ int samples;
++
++ /**
++ * Desired render buffer.
++ */
++ enum st_attachment_type render_buffer;
++};
++
++/**
++ * Represent a windowing system drawable.
++ *
++ * The framebuffer is implemented by the state tracker manager and
++ * used by the state trackers.
++ *
++ * Instead of the winsys pokeing into the API context to figure
++ * out what buffers that might be needed in the future by the API
++ * context, it calls into the framebuffer to get the textures.
++ *
++ * This structure along with the notify_invalid_framebuffer
++ * allows framebuffers to be shared between different threads
++ * but at the same make the API context free from thread
++ * syncronisation primitves, with the exception of a small
++ * atomic flag used for notification of framebuffer dirty status.
++ *
++ * The thread syncronisation is put inside the framebuffer
++ * and only called once the framebuffer has become dirty.
++ */
++struct st_framebuffer
++{
++ /**
++ * Available for the state tracker manager to use.
++ */
++ void *st_manager_private;
++
++ /**
++ * The visual of a framebuffer.
++ */
++ const struct st_visual *visual;
++
++ /**
++ * Flush the front buffer.
++ *
++ * On some window systems, changes to the front buffers are not immediately
++ * visible. They need to be flushed.
++ *
++ * @att is one of the front buffer attachments.
++ */
++ boolean (*flush_front)(struct st_framebuffer *stfb,
++ enum st_attachment_type statt);
++
++ /**
++ * The state tracker asks for the textures it needs.
++ *
++ * It should try to only ask for attachments that it currently renders
++ * to, thus allowing the winsys to delay the allocation of textures not
++ * needed. For example front buffer attachments are not needed if you
++ * only do back buffer rendering.
++ *
++ * The implementor of this function needs to also ensure
++ * thread safty as this call might be done from multiple threads.
++ *
++ * The returned textures are owned by the caller. They should be
++ * unreferenced when no longer used. If this function is called multiple
++ * times with different sets of attachments, those buffers not included in
++ * the last call might be destroyed. This behavior might change in the
++ * future.
++ */
++ boolean (*validate)(struct st_framebuffer *stfb,
++ const enum st_attachment_type *statts,
++ unsigned count,
++ struct pipe_texture **out);
++};
++
++/**
++ * Represent a rendering context.
++ *
++ * This entity is created from st_api and used by the state tracker manager.
++ */
++struct st_context
++{
++ /**
++ * The API of the context.
++ */
++ enum st_api_type api;
++
++ /**
++ * Available for the state tracker to use.
++ */
++ void *st_api_private;
++
++ /**
++ * Destroy the context.
++ */
++ void (*destroy)(struct st_context *stctx);
++
++ /**
++ * Lock and unlock a state tracker context resource.
++ *
++ * This gives access to the underlying data structure of a state tracker
++ * context resource. Unless there is some mechanism not defined here that
++ * can lengthen the lifetime of the data structure, it is valid only until
++ * unlocked.
++ */
++ void *(*lock_resource)(struct st_context *stctx,
++ enum st_context_resource_type type, void *res);
++ void (*unlock_resource)(struct st_context *stctx,
++ enum st_context_resource_type type, void *res);
++
++ /**
++ * Invalidate the current textures that was taken from a framebuffer.
++ *
++ * The state tracker manager calls this function to let the rendering
++ * context know that it should update the textures it got from
++ * st_framebuffer::validate. It should do so at the latest time possible.
++ * Possible right before sending triangles to the pipe context.
++ *
++ * For certain platforms this function might be called from a thread other
++ * than the thread that the context is currently bound in, and must
++ * therefore be thread safe. But it is the state tracker manager's
++ * responsibility to make sure that the framebuffer is bound to the context
++ * and the API context is current for the duration of this call.
++ *
++ * Thus reducing the sync primitive needed to a single atomic flag.
++ */
++ void (*notify_invalid_framebuffer)(struct st_context *stctx,
++ struct st_framebuffer *stfb);
++
++ /**
++ * Flush all drawing from context to the pipe also flushes the pipe.
++ */
++ void (*flush)(struct st_context *stctx, unsigned flags,
++ struct pipe_fence_handle **fence);
++
++ /**
++ * Replace the texture image of a texture object at the specified level.
++ *
++ * This function is optional.
++ */
++ boolean (*teximage)(struct st_context *stctx, enum st_texture_type target,
++ int level, enum pipe_format internal_format,
++ struct pipe_texture *tex, boolean mipmap);
++
++ /**
++ * Used to implement glXCopyContext.
++ */
++ void (*copy)(struct st_context *stctx, struct st_context *stsrc,
++ unsigned mask);
++};
++
++
++/**
++ * Represent a state tracker manager.
++ *
++ * This interface is implemented by the state tracker manager. It corresponds
++ * to a "display" in the window system.
++ */
++struct st_manager
++{
++ /**
++ * Lock and unlock a state tracker manager resource.
++ *
++ * This gives access to the underlying data structure of a state tracker
++ * manager resource. Unless there is some mechanism not defined here that
++ * can lengthen the lifetime of the data structure, it is valid only until
++ * unlocked.
++ */
++ void *(*lock_resource)(struct st_manager *smapi, struct st_context *stctx,
++ enum st_manager_resource_type type, void *res);
++ void (*unlock_resource)(struct st_manager *smapi, struct st_context *stctx,
++ enum st_manager_resource_type type, void *res);
++};
++
++/**
++ * Represent a rendering API such as OpenGL or OpenVG.
++ *
++ * Implemented by the state tracker and used by the state tracker manager.
++ */
++struct st_api
++{
++ /**
++ * Destroy the API.
++ */
++ void (*destroy)(struct st_api *stapi);
++
++ /**
++ * Return an API entry point.
++ *
++ * For GL this is the same as _glapi_get_proc_address.
++ */
++ st_proc_t (*get_proc_address)(struct st_api *stapi, const char *procname);
++
++ /**
++ * Return true if the visual is supported by the state tracker.
++ */
++ boolean (*is_visual_supported)(struct st_api *stapi,
++ const struct st_visual *visual);
++
++ /**
++ * Create a rendering context.
++ *
++ * XXX: The pipe argument should go away once
++ * the pipe_screen can create contexts.
++ * XXX: Is visual needed?
++ */
++ struct st_context *(*create_context)(struct st_api *stapi,
++ struct st_manager *smapi,
++ struct pipe_context *pipe,
++ const struct st_visual *visual,
++ struct st_context *stshare);
++
++ /**
++ * Bind the context to the calling thread with draw and read as drawables.
++ */
++ boolean (*make_current)(struct st_api *stapi,
++ struct st_context *stctx,
++ struct st_framebuffer *stdraw,
++ struct st_framebuffer *stread);
++
++ /**
++ * Get the currently bound context in the calling thread.
++ */
++ struct st_context *(*get_current)(struct st_api *stapi);
++};
++
++/**
++ * Represent a state tracker.
++ *
++ * This is the entry point of a state tracker.
++ */
++struct st_module
++{
++ enum st_api_type api;
++ struct st_api *(*create_api)(void);
++};
++
++/**
++ * Return true if the visual has the specified buffers.
++ */
++static INLINE boolean
++st_visual_have_buffers(const struct st_visual *visual, unsigned mask)
++{
++ return ((visual->buffer_mask & mask) == mask);
++}
++
++/* these symbols may need to be dynamically lookup up */
++extern PUBLIC const struct st_module st_module_OpenGL;
++extern PUBLIC const struct st_module st_module_OpenGL_ES1;
++extern PUBLIC const struct st_module st_module_OpenGL_ES2;
++extern PUBLIC const struct st_module st_module_OpenVG;
++
++#endif /* _ST_API_H_ */
+--
+1.6.5
+
diff --git a/sample-implementation-tmp/0002-gallium-Suffix-st_framebuffer-and-st_context-with-_i.patch b/sample-implementation-tmp/0002-gallium-Suffix-st_framebuffer-and-st_context-with-_i.patch
new file mode 100644
index 0000000..22990fd
--- /dev/null
+++ b/sample-implementation-tmp/0002-gallium-Suffix-st_framebuffer-and-st_context-with-_i.patch
@@ -0,0 +1,175 @@
+From e2bd293a0f9c775487ea007c72ba9feca2a52afc Mon Sep 17 00:00:00 2001
+From: Chia-I Wu <olvaffe@gmail.com>
+Date: Tue, 2 Feb 2010 13:45:53 +0800
+Subject: [PATCH 2/5] gallium: Suffix st_framebuffer and st_context with _iface.
+
+---
+ src/gallium/include/state_tracker/st_api.h | 54 ++++++++++++++-------------
+ 1 files changed, 28 insertions(+), 26 deletions(-)
+
+diff --git a/src/gallium/include/state_tracker/st_api.h b/src/gallium/include/state_tracker/st_api.h
+index 8feaade..5a47b63 100644
+--- a/src/gallium/include/state_tracker/st_api.h
++++ b/src/gallium/include/state_tracker/st_api.h
+@@ -63,7 +63,7 @@ enum st_api_type {
+ };
+
+ /**
+- * Used in st_context->teximage.
++ * Used in st_context_iface->teximage.
+ */
+ enum st_texture_type {
+ ST_TEXTURE_1D,
+@@ -175,7 +175,7 @@ struct st_visual
+ * The thread syncronisation is put inside the framebuffer
+ * and only called once the framebuffer has become dirty.
+ */
+-struct st_framebuffer
++struct st_framebuffer_iface
+ {
+ /**
+ * Available for the state tracker manager to use.
+@@ -195,7 +195,7 @@ struct st_framebuffer
+ *
+ * @att is one of the front buffer attachments.
+ */
+- boolean (*flush_front)(struct st_framebuffer *stfb,
++ boolean (*flush_front)(struct st_framebuffer_iface *stfbi,
+ enum st_attachment_type statt);
+
+ /**
+@@ -215,7 +215,7 @@ struct st_framebuffer
+ * the last call might be destroyed. This behavior might change in the
+ * future.
+ */
+- boolean (*validate)(struct st_framebuffer *stfb,
++ boolean (*validate)(struct st_framebuffer_iface *stfbi,
+ const enum st_attachment_type *statts,
+ unsigned count,
+ struct pipe_texture **out);
+@@ -226,7 +226,7 @@ struct st_framebuffer
+ *
+ * This entity is created from st_api and used by the state tracker manager.
+ */
+-struct st_context
++struct st_context_iface
+ {
+ /**
+ * The API of the context.
+@@ -241,7 +241,7 @@ struct st_context
+ /**
+ * Destroy the context.
+ */
+- void (*destroy)(struct st_context *stctx);
++ void (*destroy)(struct st_context_iface *stctxi);
+
+ /**
+ * Lock and unlock a state tracker context resource.
+@@ -251,9 +251,9 @@ struct st_context
+ * can lengthen the lifetime of the data structure, it is valid only until
+ * unlocked.
+ */
+- void *(*lock_resource)(struct st_context *stctx,
++ void *(*lock_resource)(struct st_context_iface *stctxi,
+ enum st_context_resource_type type, void *res);
+- void (*unlock_resource)(struct st_context *stctx,
++ void (*unlock_resource)(struct st_context_iface *stctxi,
+ enum st_context_resource_type type, void *res);
+
+ /**
+@@ -261,7 +261,7 @@ struct st_context
+ *
+ * The state tracker manager calls this function to let the rendering
+ * context know that it should update the textures it got from
+- * st_framebuffer::validate. It should do so at the latest time possible.
++ * st_framebuffer_iface::validate. It should do so at the latest time possible.
+ * Possible right before sending triangles to the pipe context.
+ *
+ * For certain platforms this function might be called from a thread other
+@@ -272,13 +272,13 @@ struct st_context
+ *
+ * Thus reducing the sync primitive needed to a single atomic flag.
+ */
+- void (*notify_invalid_framebuffer)(struct st_context *stctx,
+- struct st_framebuffer *stfb);
++ void (*notify_invalid_framebuffer)(struct st_context_iface *stctxi,
++ struct st_framebuffer_iface *stfbi);
+
+ /**
+ * Flush all drawing from context to the pipe also flushes the pipe.
+ */
+- void (*flush)(struct st_context *stctx, unsigned flags,
++ void (*flush)(struct st_context_iface *stctxi, unsigned flags,
+ struct pipe_fence_handle **fence);
+
+ /**
+@@ -286,15 +286,15 @@ struct st_context
+ *
+ * This function is optional.
+ */
+- boolean (*teximage)(struct st_context *stctx, enum st_texture_type target,
++ boolean (*teximage)(struct st_context_iface *stctxi, enum st_texture_type target,
+ int level, enum pipe_format internal_format,
+ struct pipe_texture *tex, boolean mipmap);
+
+ /**
+ * Used to implement glXCopyContext.
+ */
+- void (*copy)(struct st_context *stctx, struct st_context *stsrc,
+- unsigned mask);
++ void (*copy)(struct st_context_iface *stctxi,
++ struct st_context_iface *stsrci, unsigned mask);
+ };
+
+
+@@ -314,9 +314,11 @@ struct st_manager
+ * can lengthen the lifetime of the data structure, it is valid only until
+ * unlocked.
+ */
+- void *(*lock_resource)(struct st_manager *smapi, struct st_context *stctx,
++ void *(*lock_resource)(struct st_manager *smapi,
++ struct st_context_iface *stctxi,
+ enum st_manager_resource_type type, void *res);
+- void (*unlock_resource)(struct st_manager *smapi, struct st_context *stctx,
++ void (*unlock_resource)(struct st_manager *smapi,
++ struct st_context_iface *stctxi,
+ enum st_manager_resource_type type, void *res);
+ };
+
+@@ -352,24 +354,24 @@ struct st_api
+ * the pipe_screen can create contexts.
+ * XXX: Is visual needed?
+ */
+- struct st_context *(*create_context)(struct st_api *stapi,
+- struct st_manager *smapi,
+- struct pipe_context *pipe,
+- const struct st_visual *visual,
+- struct st_context *stshare);
++ struct st_context_iface *(*create_context)(struct st_api *stapi,
++ struct st_manager *smapi,
++ struct pipe_context *pipe,
++ const struct st_visual *visual,
++ struct st_context_iface *stsharei);
+
+ /**
+ * Bind the context to the calling thread with draw and read as drawables.
+ */
+ boolean (*make_current)(struct st_api *stapi,
+- struct st_context *stctx,
+- struct st_framebuffer *stdraw,
+- struct st_framebuffer *stread);
++ struct st_context_iface *stctxi,
++ struct st_framebuffer_iface *stdrawi,
++ struct st_framebuffer_iface *streadi);
+
+ /**
+ * Get the currently bound context in the calling thread.
+ */
+- struct st_context *(*get_current)(struct st_api *stapi);
++ struct st_context_iface *(*get_current)(struct st_api *stapi);
+ };
+
+ /**
+--
+1.6.5
+
diff --git a/sample-implementation-tmp/0003-st-vega-Implement-st_api-interface.patch b/sample-implementation-tmp/0003-st-vega-Implement-st_api-interface.patch
new file mode 100644
index 0000000..4e47567
--- /dev/null
+++ b/sample-implementation-tmp/0003-st-vega-Implement-st_api-interface.patch
@@ -0,0 +1,504 @@
+From 9cb428781f56af4e210669ed6a1cfd6381932aac Mon Sep 17 00:00:00 2001
+From: Chia-I Wu <olvaffe@gmail.com>
+Date: Thu, 14 Jan 2010 12:19:32 +0800
+Subject: [PATCH 3/5] st/vega: Implement st_api interface.
+
+---
+ src/gallium/state_trackers/vega/Makefile | 1 +
+ src/gallium/state_trackers/vega/api_context.c | 3 +
+ src/gallium/state_trackers/vega/api_masks.c | 5 +-
+ src/gallium/state_trackers/vega/vg_api.c | 368 +++++++++++++++++++++++++
+ src/gallium/state_trackers/vega/vg_api.h | 18 ++
+ src/gallium/state_trackers/vega/vg_context.h | 6 +
+ 6 files changed, 398 insertions(+), 3 deletions(-)
+ create mode 100644 src/gallium/state_trackers/vega/vg_api.c
+ create mode 100644 src/gallium/state_trackers/vega/vg_api.h
+
+diff --git a/src/gallium/state_trackers/vega/Makefile b/src/gallium/state_trackers/vega/Makefile
+index 037d8dc..1f0d0e5 100644
+--- a/src/gallium/state_trackers/vega/Makefile
++++ b/src/gallium/state_trackers/vega/Makefile
+@@ -24,6 +24,7 @@ VG_SOURCES = \
+ api_text.c \
+ api_transform.c \
+ vgu.c \
++ vg_api.c \
+ vg_context.c \
+ vg_state.c \
+ vg_tracker.c \
+diff --git a/src/gallium/state_trackers/vega/api_context.c b/src/gallium/state_trackers/vega/api_context.c
+index 47db102..de3f44a 100644
+--- a/src/gallium/state_trackers/vega/api_context.c
++++ b/src/gallium/state_trackers/vega/api_context.c
+@@ -26,6 +26,7 @@
+
+ #include "VG/openvg.h"
+
++#include "vg_api.h"
+ #include "vg_context.h"
+
+ #include "pipe/p_context.h"
+@@ -55,6 +56,8 @@ void vgFlush(void)
+
+ pipe = ctx->pipe;
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
++
++ st_flush_frontbuffer();
+ }
+
+ void vgFinish(void)
+diff --git a/src/gallium/state_trackers/vega/api_masks.c b/src/gallium/state_trackers/vega/api_masks.c
+index 9c123a4..9a308f9 100644
+--- a/src/gallium/state_trackers/vega/api_masks.c
++++ b/src/gallium/state_trackers/vega/api_masks.c
+@@ -29,6 +29,7 @@
+ #include "mask.h"
+ #include "renderer.h"
+
++#include "vg_api.h"
+ #include "vg_context.h"
+ #include "pipe/p_context.h"
+ #include "util/u_inlines.h"
+@@ -115,9 +116,7 @@ clear_with_quad(struct vg_context *st, float x0, float y0,
+ x1, y1);
+ */
+
+- if (st->pipe->screen && st->pipe->screen->update_buffer)
+- st->pipe->screen->update_buffer( st->pipe->screen,
+- st->pipe->priv );
++ st_validate_buffer();
+
+ cso_save_blend(st->cso_context);
+ cso_save_rasterizer(st->cso_context);
+diff --git a/src/gallium/state_trackers/vega/vg_api.c b/src/gallium/state_trackers/vega/vg_api.c
+new file mode 100644
+index 0000000..dcde186
+--- /dev/null
++++ b/src/gallium/state_trackers/vega/vg_api.c
+@@ -0,0 +1,368 @@
++#include "state_tracker/st_api.h"
++
++#include "pipe/p_context.h"
++#include "pipe/p_screen.h"
++#include "util/u_memory.h"
++#include "util/u_inlines.h"
++
++#include "vg_api.h"
++#include "vg_context.h"
++#include "vg_tracker.h" /* for st_resize_framebuffer */
++#include "image.h"
++
++/**
++ * Return a reference to the pipe texture of the EGLImage.
++ */
++struct pipe_texture *
++st_manager_reference_egl_image(VGeglImageKHR eglimg)
++{
++ struct vg_context *ctx = vg_current_context();
++ struct st_manager *smapi = ctx->iface.st_api_private;
++ struct pipe_texture *pt = NULL, *res;
++
++ if (!smapi)
++ return NULL;
++
++ res = (struct pipe_texture *) smapi->lock_resource(smapi, &ctx->iface,
++ ST_MANAGER_RESOURCE_EGL_IMAGE, (void *) eglimg);
++ pipe_texture_reference(&pt, res);
++ smapi->unlock_resource(smapi, &ctx->iface,
++ ST_MANAGER_RESOURCE_EGL_IMAGE, (void *) eglimg);
++
++ return pt;
++}
++
++/**
++ * Flush the front buffer if the current context renders to the front buffer.
++ */
++void
++st_flush_frontbuffer(void)
++{
++ struct vg_context *ctx = vg_current_context();
++ struct st_framebuffer *stfb = ctx->draw_buffer;
++
++ if (stfb) {
++ switch (stfb->strb_att) {
++ case ST_ATTACHMENT_FRONT_LEFT:
++ case ST_ATTACHMENT_FRONT_RIGHT:
++ stfb->iface->flush_front(stfb->iface, stfb->strb_att);
++ break;
++ default:
++ break;
++ }
++ }
++}
++
++/**
++ * Re-validate the framebuffer.
++ */
++void
++st_validate_buffer(void)
++{
++ struct vg_context *ctx = vg_current_context();
++ struct st_framebuffer *stfb = ctx->draw_buffer;
++
++ if (stfb)
++ ctx->iface.notify_invalid_framebuffer(&ctx->iface, stfb->iface);
++}
++
++
++static void
++st_context_notify_invalid_framebuffer(struct st_context_iface *stctxi,
++ struct st_framebuffer_iface *stfbi)
++{
++ struct vg_context *ctx = (struct vg_context *) stctxi;
++ struct pipe_screen *screen = ctx->pipe->screen;
++ struct st_framebuffer *stfb = ctx->draw_buffer;
++ struct st_renderbuffer *rb;
++ struct pipe_texture *pt;
++
++ /* no binding surface */
++ if (!stfb)
++ return;
++
++ assert(stfb->iface == stfbi);
++ if (stfb->strb_att == ST_ATTACHMENT_INVALID)
++ return;
++
++ /* validate the fb */
++ if (!stfb->iface->validate(stfb->iface, &stfb->strb_att, 1, &pt) || !pt)
++ return;
++
++ rb = stfb->strb;
++ if (rb->texture == pt) {
++ pipe_texture_reference(&pt, NULL);
++ return;
++ }
++
++ /* unreference existing ones */
++ pipe_surface_reference(&rb->surface, NULL);
++ pipe_texture_reference(&rb->texture, NULL);
++
++ rb->texture = pt;
++ rb->surface = screen->get_tex_surface(screen, rb->texture, 0, 0, 0,
++ PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE);
++
++ rb->width = rb->surface->width;
++ rb->height = rb->surface->height;
++
++ st_resize_framebuffer(stfb, rb->width, rb->height);
++}
++
++static void
++st_context_flush(struct st_context_iface *stctxi, unsigned flags,
++ struct pipe_fence_handle **fence)
++{
++ struct vg_context *ctx = (struct vg_context *) stctxi;
++ ctx->pipe->flush(ctx->pipe, flags, fence);
++}
++
++static void *
++st_context_lock_resource(struct st_context_iface *stctxi,
++ enum st_context_resource_type type, void *res)
++{
++ struct vg_image *img;
++ struct pipe_texture *pt = NULL;
++
++ if (type != ST_CONTEXT_RESOURCE_OPENVG_PARENT_IMAGE ||
++ (VGImage) res == VG_INVALID_HANDLE)
++ return NULL;
++
++ /* mark the image locked? */
++ img = (struct vg_image *) res;
++ pipe_texture_reference(&pt, img->texture);
++
++ return (void *) pt;
++}
++
++static void
++st_context_unlock_resource(struct st_context_iface *stctxi,
++ enum st_context_resource_type type, void *res)
++{
++ struct vg_image *img;
++ struct pipe_texture *pt;
++
++ if (type != ST_CONTEXT_RESOURCE_OPENVG_PARENT_IMAGE ||
++ (VGImage) res == VG_INVALID_HANDLE)
++ return;
++
++ img = (struct vg_image *) res;
++ pt = img->texture;
++ pipe_texture_reference(&pt, NULL);
++}
++
++static void
++st_context_destroy(struct st_context_iface *stctxi)
++{
++ struct vg_context *ctx = (struct vg_context *) stctxi;
++ vg_destroy_context(ctx);
++}
++
++static struct st_context_iface *
++st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
++ struct pipe_context *pipe,
++ const struct st_visual *visual,
++ struct st_context_iface *shared_stctxi)
++{
++ struct vg_context *shared_ctx = (struct vg_context *) shared_stctxi;
++ struct vg_context *ctx;
++
++ ctx = vg_create_context(pipe, NULL, shared_ctx);
++ if (!ctx)
++ return NULL;
++
++ ctx->iface.api = ST_API_OPENVG;
++ ctx->iface.destroy = st_context_destroy;
++ ctx->iface.lock_resource = st_context_lock_resource;
++ ctx->iface.unlock_resource = st_context_unlock_resource;
++
++ ctx->iface.notify_invalid_framebuffer =
++ st_context_notify_invalid_framebuffer;
++ ctx->iface.flush = st_context_flush;
++
++ ctx->iface.teximage = NULL;
++ ctx->iface.copy = NULL;
++
++ ctx->iface.st_api_private = (void *) smapi;
++
++ return &ctx->iface;
++}
++
++static struct st_renderbuffer *
++create_renderbuffer(enum pipe_format format)
++{
++ struct st_renderbuffer *strb;
++
++ strb = CALLOC_STRUCT(st_renderbuffer);
++ if (strb)
++ strb->format = format;
++
++ return strb;
++}
++
++static void
++destroy_renderbuffer(struct st_renderbuffer *strb)
++{
++ pipe_surface_reference(&strb->surface, NULL);
++ pipe_texture_reference(&strb->texture, NULL);
++ free(strb);
++}
++
++/**
++ * Return the attachment of the render buffer.
++ */
++static enum st_attachment_type
++choose_attachment(struct st_framebuffer_iface *stfbi)
++{
++ enum st_attachment_type statt;
++
++ statt = stfbi->visual->render_buffer;
++ if (!st_visual_have_buffers(stfbi->visual, 1 << statt)) {
++ switch (statt) {
++ case ST_ATTACHMENT_BACK_LEFT:
++ statt = ST_ATTACHMENT_FRONT_LEFT;
++ break;
++ case ST_ATTACHMENT_BACK_RIGHT:
++ statt = ST_ATTACHMENT_FRONT_RIGHT;
++ break;
++ default:
++ break;
++ }
++
++ if (!st_visual_have_buffers(stfbi->visual, 1 << statt))
++ statt = ST_ATTACHMENT_INVALID;
++ }
++
++ return statt;
++}
++
++static boolean
++st_context_bind_framebuffers(struct st_context_iface *stctxi,
++ struct st_framebuffer_iface *stdrawi,
++ struct st_framebuffer_iface *streadi)
++{
++ struct vg_context *ctx = (struct vg_context *) stctxi;
++ struct st_framebuffer *stfb;
++
++ if (stdrawi != streadi)
++ return FALSE;
++
++ if (ctx->draw_buffer) {
++ stfb = ctx->draw_buffer;
++
++ /* free the existing fb */
++ if (!stdrawi ||
++ stfb->strb->format != stdrawi->visual->color_format ||
++ stfb->dsrb->format != stdrawi->visual->depth_stencil_format) {
++ destroy_renderbuffer(stfb->strb);
++ destroy_renderbuffer(stfb->dsrb);
++ free(stfb);
++
++ ctx->draw_buffer = NULL;
++ }
++ }
++
++ if (!stdrawi)
++ return TRUE;
++
++ /* create a new fb */
++ if (!ctx->draw_buffer) {
++ stfb = CALLOC_STRUCT(st_framebuffer);
++ if (!stfb)
++ return FALSE;
++
++ stfb->strb = create_renderbuffer(stdrawi->visual->color_format);
++ if (!stfb->strb) {
++ free(stfb);
++ return FALSE;
++ }
++
++ stfb->dsrb = create_renderbuffer(stdrawi->visual->depth_stencil_format);
++ if (!stfb->dsrb) {
++ free(stfb->strb);
++ free(stfb);
++ return FALSE;
++ }
++
++ stfb->width = 0;
++ stfb->height = 0;
++
++ ctx->draw_buffer = stfb;
++ }
++
++ ctx->draw_buffer->iface = stdrawi;
++ ctx->draw_buffer->strb_att = choose_attachment(stdrawi);
++
++ return TRUE;
++}
++
++static boolean
++st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
++ struct st_framebuffer_iface *stdrawi,
++ struct st_framebuffer_iface *streadi)
++{
++ struct vg_context *ctx = (struct vg_context *) stctxi;
++
++ if (stctxi)
++ st_context_bind_framebuffers(stctxi, stdrawi, streadi);
++ vg_set_current_context(ctx);
++
++ return TRUE;
++}
++
++static struct st_context_iface *
++st_api_get_current(struct st_api *stapi)
++{
++ struct vg_context *ctx = vg_current_context();
++
++ return (ctx) ? &ctx->iface : NULL;
++}
++
++static st_proc_t
++st_api_get_proc_address(struct st_api *stapi, const char *procname)
++{
++ /* TODO */
++ return (st_proc_t) NULL;
++}
++
++static boolean
++st_api_is_visual_supported(struct st_api *stapi,
++ const struct st_visual *visual)
++{
++ /* the impl requires a depth/stencil buffer */
++ if (visual->depth_stencil_format == PIPE_FORMAT_NONE)
++ return FALSE;
++
++ return TRUE;
++}
++
++static void
++st_api_destroy(struct st_api *stapi)
++{
++ free(stapi);
++}
++
++static struct st_api *
++st_module_create_api(void)
++{
++ struct st_api *stapi;
++
++ stapi = CALLOC_STRUCT(st_api);
++ if (stapi) {
++ stapi->destroy = st_api_destroy;
++ stapi->is_visual_supported = st_api_is_visual_supported;
++
++ stapi->create_context = st_api_create_context;
++ stapi->make_current = st_api_make_current;
++ stapi->get_current = st_api_get_current;
++
++ stapi->get_proc_address = st_api_get_proc_address;
++ }
++
++ return stapi;
++}
++
++const struct st_module st_module_OpenVG = {
++ .api = ST_API_OPENVG,
++ .create_api = st_module_create_api,
++};
+diff --git a/src/gallium/state_trackers/vega/vg_api.h b/src/gallium/state_trackers/vega/vg_api.h
+new file mode 100644
+index 0000000..06c65f0
+--- /dev/null
++++ b/src/gallium/state_trackers/vega/vg_api.h
+@@ -0,0 +1,18 @@
++#ifndef VG_API_H
++#define VG_API_H
++
++#include "VG/openvg.h"
++#include "VG/vgext.h"
++
++#include "pipe/p_state.h"
++
++struct pipe_texture *
++st_manager_reference_egl_image(VGeglImageKHR eglimg);
++
++void
++st_flush_frontbuffer(void);
++
++void
++st_validate_buffer(void);
++
++#endif /* VG_API_H */
+diff --git a/src/gallium/state_trackers/vega/vg_context.h b/src/gallium/state_trackers/vega/vg_context.h
+index bc88c8d..91300ff 100644
+--- a/src/gallium/state_trackers/vega/vg_context.h
++++ b/src/gallium/state_trackers/vega/vg_context.h
+@@ -33,6 +33,7 @@
+ #include "pipe/p_state.h"
+ #include "util/u_pointer.h"
+ #include "util/u_math.h"
++#include "state_tracker/st_api.h"
+
+ #include "cso_cache/cso_hash.h"
+ #include "cso_cache/cso_context.h"
+@@ -58,6 +59,9 @@ struct st_framebuffer {
+
+ struct pipe_texture *blend_texture;
+
++ struct st_framebuffer_iface *iface;
++ enum st_attachment_type strb_att;
++
+ void *privateData;
+ };
+
+@@ -84,6 +88,8 @@ enum dirty_state {
+
+ struct vg_context
+ {
++ struct st_context_iface iface;
++
+ struct pipe_context *pipe;
+
+ struct {
+--
+1.6.5
+
diff --git a/sample-implementation-tmp/0004-st-egl-Add-support-for-loading-st_api-modules.patch b/sample-implementation-tmp/0004-st-egl-Add-support-for-loading-st_api-modules.patch
new file mode 100644
index 0000000..a8dcce3
--- /dev/null
+++ b/sample-implementation-tmp/0004-st-egl-Add-support-for-loading-st_api-modules.patch
@@ -0,0 +1,189 @@
+From f8f6f9c3917a72da94b36912f1cbd0303899a191 Mon Sep 17 00:00:00 2001
+From: Chia-I Wu <olvaffe@gmail.com>
+Date: Thu, 14 Jan 2010 16:05:36 +0800
+Subject: [PATCH 4/5] st/egl: Add support for loading st_api modules.
+
+---
+ src/gallium/state_trackers/egl/common/egl_st_api.c | 116 ++++++++++++++++++++
+ src/gallium/state_trackers/egl/common/egl_st_api.h | 46 ++++++++
+ 2 files changed, 162 insertions(+), 0 deletions(-)
+ create mode 100644 src/gallium/state_trackers/egl/common/egl_st_api.c
+ create mode 100644 src/gallium/state_trackers/egl/common/egl_st_api.h
+
+diff --git a/src/gallium/state_trackers/egl/common/egl_st_api.c b/src/gallium/state_trackers/egl/common/egl_st_api.c
+new file mode 100644
+index 0000000..bfcc49e
+--- /dev/null
++++ b/src/gallium/state_trackers/egl/common/egl_st_api.c
+@@ -0,0 +1,116 @@
++#include "util/u_memory.h"
++#include "util/u_dl.h"
++#include "eglimage.h"
++
++#include "egl_st_api.h"
++
++struct egl_g3d_st_manager {
++ struct st_manager base;
++ _EGLDisplay *display;
++};
++
++static INLINE struct egl_g3d_st_manager *
++egl_g3d_st_manager(struct st_manager *smapi)
++{
++ return (struct egl_g3d_st_manager *) smapi;
++}
++
++static void *
++egl_g3d_st_manager_lock_resource(struct st_manager *smapi,
++ struct st_context_iface *stctxi,
++ enum st_manager_resource_type type,
++ void *res)
++{
++ struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
++ void *ret;
++
++ switch (type) {
++ case ST_MANAGER_RESOURCE_EGL_IMAGE:
++ {
++ EGLImageKHR handle = (EGLImageKHR) res;
++ _EGLImage *img = _eglLookupImage(handle, gsmapi->display);
++
++ /* TODO retrieve the pipe texture of the image */
++ (void) img;
++
++ ret = NULL;
++ }
++ break;
++ default:
++ ret = NULL;
++ break;
++ }
++
++ return ret;
++}
++
++static void
++egl_g3d_st_manager_unlock_resource(struct st_manager *smapi,
++ struct st_context_iface *stctxi,
++ enum st_manager_resource_type type,
++ void *res)
++{
++}
++
++struct st_manager *
++egl_g3d_create_st_manager(_EGLDisplay *dpy)
++{
++ struct egl_g3d_st_manager *gsmapi;
++
++ gsmapi = CALLOC_STRUCT(egl_g3d_st_manager);
++ if (gsmapi) {
++ gsmapi->display = dpy;
++
++ gsmapi->base.lock_resource = egl_g3d_st_manager_lock_resource;
++ gsmapi->base.unlock_resource = egl_g3d_st_manager_unlock_resource;
++ }
++
++ return &gsmapi->base;;
++}
++
++void
++egl_g3d_destroy_st_manager(struct st_manager *smapi)
++{
++ struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
++ free(gsmapi);
++}
++
++struct st_api *
++egl_g3d_create_st_api(enum st_api_type api)
++{
++ const char *stmod_name;
++ struct util_dl_library *lib;
++ const struct st_module *mod;
++
++ switch (api) {
++ case ST_API_OPENGL:
++ stmod_name = ST_MODULE_OPENGL_SYMBOL;
++ break;
++ case ST_API_OPENGL_ES1:
++ stmod_name = ST_MODULE_OPENGL_ES1_SYMBOL;
++ break;
++ case ST_API_OPENGL_ES2:
++ stmod_name = ST_MODULE_OPENGL_ES2_SYMBOL;
++ break;
++ case ST_API_OPENVG:
++ stmod_name = ST_MODULE_OPENVG_SYMBOL;
++ break;
++ default:
++ stmod_name = NULL;
++ break;
++ }
++ if (!stmod_name)
++ return NULL;
++
++ mod = NULL;
++ lib = util_dl_open(NULL);
++ if (lib) {
++ mod = (const struct st_module *)
++ util_dl_get_proc_address(lib, stmod_name);
++ util_dl_close(lib);
++ }
++ if (!mod || mod->api != api)
++ return NULL;
++
++ return mod->create_api();
++}
+diff --git a/src/gallium/state_trackers/egl/common/egl_st_api.h b/src/gallium/state_trackers/egl/common/egl_st_api.h
+new file mode 100644
+index 0000000..f39f318
+--- /dev/null
++++ b/src/gallium/state_trackers/egl/common/egl_st_api.h
+@@ -0,0 +1,46 @@
++#ifndef _EGL_ST_API_H_
++#define _EGL_ST_API_H_
++
++#include "pipe/p_compiler.h"
++#include "state_tracker/st_api.h"
++#include "egltypedefs.h"
++
++struct st_manager *
++egl_g3d_create_st_manager(_EGLDisplay *dpy);
++
++void
++egl_g3d_destroy_st_manager(struct st_manager *smapi);
++
++struct st_api *
++egl_g3d_create_st_api(enum st_api_type api);
++
++/**
++ * Return the EGL_<api>_BIT of the st api.
++ */
++static INLINE int
++egl_g3d_st_api_bit(enum st_api_type api)
++{
++ int bit;
++
++ switch (api) {
++ case ST_API_OPENGL:
++ bit = EGL_OPENGL_BIT;
++ break;
++ case ST_API_OPENGL_ES1:
++ bit = EGL_OPENGL_ES_BIT;
++ break;
++ case ST_API_OPENGL_ES2:
++ bit = EGL_OPENGL_ES2_BIT;
++ break;
++ case ST_API_OPENVG:
++ bit = EGL_OPENVG_BIT;
++ break;
++ default:
++ bit = 0;
++ break;
++ }
++
++ return bit;
++}
++
++#endif /* _EGL_ST_API_H_ */
+--
+1.6.5
+
diff --git a/sample-implementation-tmp/0005-st-egl-Use-st_api.h-instead-of-st_public.h.patch b/sample-implementation-tmp/0005-st-egl-Use-st_api.h-instead-of-st_public.h.patch
new file mode 100644
index 0000000..f5dbec7
--- /dev/null
+++ b/sample-implementation-tmp/0005-st-egl-Use-st_api.h-instead-of-st_public.h.patch
@@ -0,0 +1,1103 @@
+From 61f5bc139286416251a1e42fad239b53feaa654c Mon Sep 17 00:00:00 2001
+From: Chia-I Wu <olvaffe@gmail.com>
+Date: Mon, 25 Jan 2010 22:18:29 +0800
+Subject: [PATCH 5/5] st/egl: Use st_api.h instead of st_public.h.
+
+---
+ src/gallium/state_trackers/egl/common/egl_g3d.c | 539 ++++++++------------
+ src/gallium/state_trackers/egl/common/egl_g3d.h | 19 +-
+ src/gallium/state_trackers/egl/common/egl_st.c | 131 -----
+ src/gallium/state_trackers/egl/common/egl_st.h | 73 ---
+ .../state_trackers/egl/common/st_public_tmp.h | 20 -
+ 5 files changed, 233 insertions(+), 549 deletions(-)
+ delete mode 100644 src/gallium/state_trackers/egl/common/egl_st.c
+ delete mode 100644 src/gallium/state_trackers/egl/common/egl_st.h
+ delete mode 100644 src/gallium/state_trackers/egl/common/st_public_tmp.h
+
+diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c
+index 7021617..8c51e99 100644
+--- a/src/gallium/state_trackers/egl/common/egl_g3d.c
++++ b/src/gallium/state_trackers/egl/common/egl_g3d.c
+@@ -36,233 +36,26 @@
+
+ #include "native.h"
+ #include "egl_g3d.h"
+-#include "egl_st.h"
+-
+-/**
+- * Validate the draw/read surfaces of the context.
+- */
+-static void
+-egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
+-{
+- struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+- struct pipe_screen *screen = gdpy->native->screen;
+- struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+- const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = {
+- ST_SURFACE_FRONT_LEFT,
+- ST_SURFACE_BACK_LEFT,
+- ST_SURFACE_FRONT_RIGHT,
+- ST_SURFACE_BACK_RIGHT,
+- };
+- EGLint num_surfaces, s;
+-
+- /* validate draw and/or read buffers */
+- num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2;
+- for (s = 0; s < num_surfaces; s++) {
+- struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
+- struct egl_g3d_surface *gsurf;
+- struct egl_g3d_buffer *gbuf;
+- EGLint att;
+-
+- if (s == 0) {
+- gsurf = egl_g3d_surface(gctx->base.DrawSurface);
+- gbuf = &gctx->draw;
+- }
+- else {
+- gsurf = egl_g3d_surface(gctx->base.ReadSurface);
+- gbuf = &gctx->read;
+- }
+-
+- if (!gctx->force_validate) {
+- unsigned int seq_num;
+-
+- gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
+- &seq_num, NULL, NULL, NULL);
+- /* skip validation */
+- if (gsurf->sequence_number == seq_num)
+- continue;
+- }
+-
+- pipe_surface_reference(&gsurf->render_surface, NULL);
+- memset(textures, 0, sizeof(textures));
+-
+- gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
+- &gsurf->sequence_number, textures,
+- &gsurf->base.Width, &gsurf->base.Height);
+- for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+- struct pipe_texture *pt = textures[att];
+- struct pipe_surface *ps;
+-
+- if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) {
+- ps = screen->get_tex_surface(screen, pt, 0, 0, 0,
+- PIPE_BUFFER_USAGE_GPU_READ |
+- PIPE_BUFFER_USAGE_GPU_WRITE);
+- gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb,
+- st_att_map[att], ps);
+-
+- if (gsurf->render_att == att)
+- pipe_surface_reference(&gsurf->render_surface, ps);
+-
+- pipe_surface_reference(&ps, NULL);
+- pipe_texture_reference(&pt, NULL);
+- }
+- }
+-
+- gctx->stapi->st_resize_framebuffer(gbuf->st_fb,
+- gsurf->base.Width, gsurf->base.Height);
+- }
+-
+- gctx->force_validate = EGL_FALSE;
+-
+-}
+-
+-/**
+- * Create a st_framebuffer.
+- */
+-static struct st_framebuffer *
+-create_framebuffer(_EGLContext *ctx, _EGLSurface *surf)
+-{
+- struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+- struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+- struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
+-
+- return gctx->stapi->st_create_framebuffer(&gconf->native->mode,
+- gconf->native->color_format, gconf->native->depth_format,
+- gconf->native->stencil_format,
+- gsurf->base.Width, gsurf->base.Height, &gsurf->base);
+-}
+-
+-/**
+- * Update the attachments of draw/read surfaces.
+- */
+-static void
+-egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx)
+-{
+- struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+- EGLint s;
+-
+- /* route draw and read buffers' attachments */
+- for (s = 0; s < 2; s++) {
+- struct egl_g3d_surface *gsurf;
+- struct egl_g3d_buffer *gbuf;
+-
+- if (s == 0) {
+- gsurf = egl_g3d_surface(gctx->base.DrawSurface);
+- gbuf = &gctx->draw;
+- }
+- else {
+- gsurf = egl_g3d_surface(gctx->base.ReadSurface);
+- gbuf = &gctx->read;
+- }
+-
+- gbuf->attachment_mask = (1 << gsurf->render_att);
+-
+- /* FIXME OpenGL defaults to draw the front or back buffer when the
+- * context is single-buffered or double-buffered respectively. In EGL,
+- * however, the buffer to be drawn is determined by the surface, instead
+- * of the context. As a result, rendering to a pixmap surface with a
+- * double-buffered context does not work as expected.
+- *
+- * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt ==
+- * NATIVE_ATTACHMENT_FRONT_LEFT);
+- */
+-
+- /*
+- * FIXME If the back buffer is asked for here, and the front buffer is
+- * later needed by the client API (e.g. glDrawBuffer is called to draw
+- * the front buffer), it will create a new pipe texture and draw there.
+- * One fix is to ask for both buffers here, but it would be a waste if
+- * the front buffer is never used. A better fix is to add a callback to
+- * the pipe screen with context private (just like flush_frontbuffer).
+- */
+- }
+-}
+-
+-/**
+- * Reallocate the context's framebuffers after draw/read surfaces change.
+- */
+-static EGLBoolean
+-egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx)
+-{
+- struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+- struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface);
+- struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface);
+-
+- /* unreference the old framebuffers */
+- if (gctx->draw.st_fb) {
+- EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb);
+- void *priv;
+-
+- priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb);
+- if (!gdraw || priv != (void *) &gdraw->base) {
+- gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
+- gctx->draw.st_fb = NULL;
+- gctx->draw.attachment_mask = 0x0;
+- }
+-
+- if (is_equal) {
+- gctx->read.st_fb = NULL;
+- gctx->draw.attachment_mask = 0x0;
+- }
+- else {
+- priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb);
+- if (!gread || priv != (void *) &gread->base) {
+- gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb);
+- gctx->read.st_fb = NULL;
+- gctx->draw.attachment_mask = 0x0;
+- }
+- }
+- }
+-
+- if (!gdraw)
+- return EGL_TRUE;
+-
+- /* create the draw fb */
+- if (!gctx->draw.st_fb) {
+- gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base);
+- if (!gctx->draw.st_fb)
+- return EGL_FALSE;
+- }
+-
+- /* create the read fb */
+- if (!gctx->read.st_fb) {
+- if (gread != gdraw) {
+- gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base);
+- if (!gctx->read.st_fb) {
+- gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
+- gctx->draw.st_fb = NULL;
+- return EGL_FALSE;
+- }
+- }
+- else {
+- /* there is no st_reference_framebuffer... */
+- gctx->read.st_fb = gctx->draw.st_fb;
+- }
+- }
+-
+- egl_g3d_route_context(dpy, &gctx->base);
+- gctx->force_validate = EGL_TRUE;
+-
+- return EGL_TRUE;
+-}
++#include "egl_st_api.h"
+
+ /**
+ * Return the state tracker for the given context.
+ */
+-static const struct egl_g3d_st *
++static struct st_api *
+ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
+ {
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+- const struct egl_g3d_st *stapi;
++ struct st_api *stapi;
+ EGLint idx = -1;
+
+ switch (ctx->ClientAPI) {
+ case EGL_OPENGL_ES_API:
+ switch (ctx->ClientVersion) {
+ case 1:
+- idx = EGL_G3D_ST_OPENGL_ES;
++ idx = ST_API_OPENGL_ES1;
+ break;
+ case 2:
+- idx = EGL_G3D_ST_OPENGL_ES2;
++ idx = ST_API_OPENGL_ES2;
+ break;
+ default:
+ _eglLog(_EGL_WARNING, "unknown client version %d",
+@@ -271,10 +64,10 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
+ }
+ break;
+ case EGL_OPENVG_API:
+- idx = EGL_G3D_ST_OPENVG;
++ idx = ST_API_OPENVG;
+ break;
+ case EGL_OPENGL_API:
+- idx = EGL_G3D_ST_OPENGL;
++ idx = ST_API_OPENGL;
+ break;
+ default:
+ _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
+@@ -298,10 +91,10 @@ egl_g3d_init_st(_EGLDriver *drv)
+ if (gdrv->api_mask)
+ return;
+
+- for (i = 0; i < NUM_EGL_G3D_STS; i++) {
+- gdrv->stapis[i] = egl_g3d_get_st(i);
++ for (i = 0; i < ST_API_COUNT; i++) {
++ gdrv->stapis[i] = egl_g3d_create_st_api(i);
+ if (gdrv->stapis[i])
+- gdrv->api_mask |= gdrv->stapis[i]->api_bit;
++ gdrv->api_mask |= egl_g3d_st_api_bit(i);
+ }
+
+ if (gdrv->api_mask)
+@@ -507,36 +300,6 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
+ return id;
+ }
+
+-/**
+- * Flush the front buffer of the context's draw surface.
+- */
+-static void
+-egl_g3d_flush_frontbuffer(struct pipe_screen *screen,
+- struct pipe_surface *surf, void *context_private)
+-{
+- struct egl_g3d_context *gctx = egl_g3d_context(context_private);
+- struct egl_g3d_surface *gsurf = egl_g3d_surface(gctx->base.DrawSurface);
+-
+- if (gsurf)
+- gsurf->native->flush_frontbuffer(gsurf->native);
+-}
+-
+-/**
+- * Re-validate the context.
+- */
+-static void
+-egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private)
+-{
+- struct egl_g3d_context *gctx = egl_g3d_context(context_private);
+-
+- /**
+- * It is likely that the surface has changed when this function is called.
+- * Set force_validate to skip an unnecessary check.
+- */
+- gctx->force_validate = EGL_TRUE;
+- egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base);
+-}
+-
+ static EGLBoolean
+ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
+ {
+@@ -555,6 +318,9 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
+ free(dpy->Screens);
+ }
+
++ if (gdpy->smapi)
++ egl_g3d_destroy_st_manager(gdpy->smapi);
++
+ if (gdpy->native)
+ gdpy->native->destroy(gdpy->native);
+
+@@ -587,9 +353,6 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
+ goto fail;
+ }
+
+- gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer;
+- gdpy->native->screen->update_buffer = egl_g3d_update_buffer;
+-
+ egl_g3d_init_st(&gdrv->base);
+ dpy->ClientAPIsMask = gdrv->api_mask;
+
+@@ -598,6 +361,13 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
+ goto fail;
+ }
+
++ gdpy->smapi = egl_g3d_create_st_manager(dpy);
++ if (!gdpy->smapi) {
++ _eglError(EGL_NOT_INITIALIZED,
++ "eglInitialize(failed to create st manager)");
++ goto fail;
++ }
++
+ #ifdef EGL_MESA_screen_surface
+ /* enable MESA_screen_surface */
+ if (gdpy->native->modeset) {
+@@ -652,9 +422,9 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
+ return NULL;
+ }
+
+- gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode,
+- (gshare) ? gshare->st_ctx : NULL);
+- if (!gctx->st_ctx) {
++ gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi,
++ gctx->pipe, NULL, (gshare) ? gshare->stctxi : NULL);
++ if (!gctx->stctxi) {
+ gctx->pipe->destroy(gctx->pipe);
+ free(gctx);
+ return NULL;
+@@ -675,9 +445,8 @@ destroy_context(_EGLDisplay *dpy, _EGLContext *ctx)
+ if (!dpy->Initialized)
+ _eglLog(_EGL_FATAL, "destroy a context with an unitialized display");
+
+- egl_g3d_realloc_context(dpy, &gctx->base);
+- /* it will destroy the associated pipe context */
+- gctx->stapi->st_destroy_context(gctx->st_ctx);
++ /* it will destroy the pipe context */
++ gctx->stctxi->destroy(gctx->stctxi);
+
+ free(gctx);
+ }
+@@ -690,6 +459,140 @@ egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
+ return EGL_TRUE;
+ }
+
++static boolean
++egl_g3d_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
++ enum st_attachment_type statt)
++{
++ _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
++ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
++
++ return gsurf->native->flush_frontbuffer(gsurf->native);
++}
++
++static boolean
++egl_g3d_framebuffer_validate(struct st_framebuffer_iface *stfbi,
++ const enum st_attachment_type *statts,
++ unsigned count,
++ struct pipe_texture **out)
++{
++ _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
++ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
++ struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
++ uint attachment_mask = 0;
++ unsigned i;
++
++ for (i = 0; i < count; i++) {
++ int natt;
++
++ switch (statts[i]) {
++ case ST_ATTACHMENT_FRONT_LEFT:
++ natt = NATIVE_ATTACHMENT_FRONT_LEFT;
++ break;
++ case ST_ATTACHMENT_BACK_LEFT:
++ natt = NATIVE_ATTACHMENT_BACK_LEFT;
++ break;
++ case ST_ATTACHMENT_FRONT_RIGHT:
++ natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
++ break;
++ case ST_ATTACHMENT_BACK_RIGHT:
++ natt = NATIVE_ATTACHMENT_BACK_RIGHT;
++ default:
++ natt = -1;
++ break;
++ }
++
++ if (natt >= 0)
++ attachment_mask |= 1 << natt;
++ }
++
++ if (!gsurf->native->validate(gsurf->native, attachment_mask,
++ &gsurf->sequence_number, textures, &gsurf->base.Width,
++ &gsurf->base.Height))
++ return FALSE;
++
++ for (i = 0; i < count; i++) {
++ struct pipe_texture *tex;
++ int natt;
++
++ switch (statts[i]) {
++ case ST_ATTACHMENT_FRONT_LEFT:
++ natt = NATIVE_ATTACHMENT_FRONT_LEFT;
++ break;
++ case ST_ATTACHMENT_BACK_LEFT:
++ natt = NATIVE_ATTACHMENT_BACK_LEFT;
++ break;
++ case ST_ATTACHMENT_FRONT_RIGHT:
++ natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
++ break;
++ case ST_ATTACHMENT_BACK_RIGHT:
++ natt = NATIVE_ATTACHMENT_BACK_RIGHT;
++ break;
++ default:
++ natt = -1;
++ break;
++ }
++
++ if (natt >= 0) {
++ tex = textures[natt];
++
++ if (attachment_mask & (1 << natt)) {
++ /* transfer the ownership to the caller */
++ out[i] = tex;
++ attachment_mask &= ~(1 << natt);
++ }
++ else {
++ /* the attachment is listed more than once */
++ pipe_texture_reference(&out[i], tex);
++ }
++ }
++ }
++
++ return TRUE;
++}
++
++static EGLBoolean
++init_surface_framebuffer(_EGLSurface *surf, _EGLConfig *conf)
++{
++ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
++ struct egl_g3d_config *gconf = egl_g3d_config(conf);
++ struct st_framebuffer_iface *stfbi;
++ unsigned buffer_mask;
++
++ stfbi = CALLOC_STRUCT(st_framebuffer_iface);
++ if (!stfbi)
++ return EGL_FALSE;
++
++ buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
++ if (gconf->native->mode.doubleBufferMode)
++ buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
++ if (gconf->native->mode.stereoMode) {
++ buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
++ if (gconf->native->mode.doubleBufferMode)
++ buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
++ }
++
++ gsurf->stvis.buffer_mask = buffer_mask;
++ gsurf->stvis.color_format = gconf->native->color_format;
++ gsurf->stvis.depth_stencil_format = gconf->native->depth_format;
++ gsurf->stvis.accum_format = PIPE_FORMAT_NONE;
++ gsurf->stvis.samples = 0;
++
++ if (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER ||
++ !(buffer_mask & ST_ATTACHMENT_BACK_LEFT))
++ gsurf->stvis.render_buffer = ST_ATTACHMENT_FRONT_LEFT;
++ else
++ gsurf->stvis.render_buffer = ST_ATTACHMENT_BACK_LEFT;
++
++ stfbi->visual = &gsurf->stvis;
++ stfbi->flush_front = egl_g3d_framebuffer_flush_front;
++ stfbi->validate = egl_g3d_framebuffer_validate;
++ stfbi->st_manager_private = (void *) &gsurf->base;
++
++ gsurf->stfbi = stfbi;
++
++ return EGL_TRUE;
++}
++
+ static EGLBoolean
+ init_surface_geometry(_EGLSurface *surf)
+ {
+@@ -727,16 +630,13 @@ egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
+ return NULL;
+ }
+
+- if (!init_surface_geometry(&gsurf->base)) {
++ if (!init_surface_geometry(&gsurf->base) ||
++ !init_surface_framebuffer(&gsurf->base, &gconf->base)) {
+ gsurf->native->destroy(gsurf->native);
+ free(gsurf);
+ return NULL;
+ }
+
+- gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER ||
+- !gconf->native->mode.doubleBufferMode) ?
+- NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
+-
+ return &gsurf->base;
+ }
+
+@@ -767,14 +667,13 @@ egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
+ return NULL;
+ }
+
+- if (!init_surface_geometry(&gsurf->base)) {
++ if (!init_surface_geometry(&gsurf->base) ||
++ !init_surface_framebuffer(&gsurf->base, &gconf->base)) {
+ gsurf->native->destroy(gsurf->native);
+ free(gsurf);
+ return NULL;
+ }
+
+- gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT;
+-
+ return &gsurf->base;
+ }
+
+@@ -805,15 +704,13 @@ egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
+ return NULL;
+ }
+
+- if (!init_surface_geometry(&gsurf->base)) {
++ if (!init_surface_geometry(&gsurf->base) ||
++ !init_surface_framebuffer(&gsurf->base, &gconf->base)) {
+ gsurf->native->destroy(gsurf->native);
+ free(gsurf);
+ return NULL;
+ }
+
+- gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ?
+- NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
+-
+ return &gsurf->base;
+ }
+
+@@ -831,6 +728,7 @@ destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
+
+ pipe_surface_reference(&gsurf->render_surface, NULL);
+ gsurf->native->destroy(gsurf->native);
++ free(gsurf->stfbi);
+ free(gsurf);
+ }
+
+@@ -848,6 +746,7 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
+ {
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+ struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
++ struct egl_g3d_surface *gread = egl_g3d_surface(read);
+ struct egl_g3d_context *old_gctx;
+ EGLBoolean ok = EGL_TRUE;
+
+@@ -858,34 +757,29 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
+
+ if (old_gctx) {
+ /* flush old context */
+- old_gctx->stapi->st_flush(old_gctx->st_ctx,
++ old_gctx->stctxi->flush(old_gctx->stctxi,
+ PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
+-
+- /*
+- * The old context is no longer current, and egl_g3d_realloc_context()
+- * should be called to destroy the framebuffers. However, it is possible
+- * that it will be made current again with the same draw/read surfaces.
+- * It might be better to keep it around.
+- */
+ }
+
+ if (gctx) {
+- ok = egl_g3d_realloc_context(dpy, &gctx->base);
++ ok = gctx->stapi->make_current(gctx->stapi, gctx->stctxi,
++ (gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL);
+ if (ok) {
+- ok = gctx->stapi->st_make_current(gctx->st_ctx,
+- gctx->draw.st_fb, gctx->read.st_fb);
+- if (ok) {
+- egl_g3d_validate_context(dpy, &gctx->base);
+- if (gdraw->base.Type == EGL_WINDOW_BIT) {
+- gctx->base.WindowRenderBuffer =
+- (gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ?
+- EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
+- }
++ gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gdraw->stfbi);
++ if (gread != gdraw) {
++ gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi,
++ gread->stfbi);
++ }
++
++ if (gdraw->base.Type == EGL_WINDOW_BIT) {
++ gctx->base.WindowRenderBuffer =
++ (gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ?
++ EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
+ }
+ }
+ }
+ else if (old_gctx) {
+- ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL);
++ ok = old_gctx->stapi->make_current(old_gctx->stapi, NULL, NULL, NULL);
+ old_gctx->base.WindowRenderBuffer = EGL_NONE;
+ }
+
+@@ -912,15 +806,17 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
+ return EGL_TRUE;
+
+ /* or when the surface is single-buffered */
+- if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT)
++ if (gsurf->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT)
+ return EGL_TRUE;
+
+ if (ctx && ctx->DrawSurface == surf)
+ gctx = egl_g3d_context(ctx);
+
+ /* flush if the surface is current */
+- if (gctx)
+- gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb);
++ if (gctx) {
++ gctx->stctxi->flush(gctx->stctxi,
++ PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
++ }
+
+ /*
+ * We drew on the back buffer, unless there was no back buffer.
+@@ -933,11 +829,9 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
+ if (gctx) {
+ struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
+
+- /* force validation if the swap method is not copy */
+- if (gconf->native->mode.swapMethod != GLX_SWAP_COPY_OML) {
+- gctx->force_validate = EGL_TRUE;
+- egl_g3d_validate_context(dpy, &gctx->base);
+- }
++ /* validate if the swap method is not copy */
++ if (gconf->native->mode.swapMethod != GLX_SWAP_COPY_OML)
++ gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
+ }
+
+ return EGL_TRUE;
+@@ -1011,7 +905,7 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
+ /* flush if the surface is current */
+ if (ctx && ctx->DrawSurface == &gsurf->base) {
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+- gctx->stapi->st_flush(gctx->st_ctx,
++ gctx->stctxi->flush(gctx->stctxi,
+ PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
+ }
+
+@@ -1041,8 +935,16 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
+ static EGLBoolean
+ egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
+ {
++ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+- gctx->stapi->st_finish(gctx->st_ctx);
++ struct pipe_screen *screen = gdpy->native->screen;
++ struct pipe_fence_handle *fence = NULL;
++
++ gctx->stctxi->flush(gctx->stctxi,
++ PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
++ screen->fence_finish(screen, fence, 0);
++ screen->fence_reference(screen, &fence, NULL);
++
+ return EGL_TRUE;
+ }
+
+@@ -1072,10 +974,10 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
+ /* in case this is called before a display is initialized */
+ egl_g3d_init_st(&gdrv->base);
+
+- for (i = 0; i < NUM_EGL_G3D_STS; i++) {
+- const struct egl_g3d_st *stapi = gdrv->stapis[i];
++ for (i = 0; i < ST_API_COUNT; i++) {
++ struct st_api *stapi = gdrv->stapis[i];
+ if (stapi) {
+- proc = (_EGLProc) stapi->st_get_proc_address(procname);
++ proc = (_EGLProc) stapi->get_proc_address(stapi, procname);
+ if (proc)
+ return proc;
+ }
+@@ -1091,8 +993,8 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
+ struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+ _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API);
+ struct egl_g3d_context *gctx;
+- enum pipe_format target_format;
+- int target;
++ enum pipe_format internal_format;
++ enum st_texture_type target;
+
+ if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
+ return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
+@@ -1103,10 +1005,10 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
+
+ switch (gsurf->base.TextureFormat) {
+ case EGL_TEXTURE_RGB:
+- target_format = PIPE_FORMAT_R8G8B8_UNORM;
++ internal_format = PIPE_FORMAT_R8G8B8_UNORM;
+ break;
+ case EGL_TEXTURE_RGBA:
+- target_format = PIPE_FORMAT_A8R8G8B8_UNORM;
++ internal_format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ break;
+ default:
+ return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+@@ -1128,15 +1030,18 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
+ /* flush properly if the surface is bound */
+ if (gsurf->base.CurrentContext) {
+ gctx = egl_g3d_context(gsurf->base.CurrentContext);
+- gctx->stapi->st_flush(gctx->st_ctx,
++ gctx->stctxi->flush(gctx->stctxi,
+ PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
+ }
+
+ gctx = egl_g3d_context(es1);
+- gctx->stapi->st_bind_texture_surface(gsurf->render_surface,
+- target, gsurf->base.MipmapLevel, target_format);
+-
+- gsurf->base.BoundToTexture = EGL_TRUE;
++ if (gctx->stctxi->teximage) {
++ if (!gctx->stctxi->teximage(gctx->stctxi, target,
++ gsurf->base.MipmapLevel, internal_format,
++ gsurf->render_surface->texture, gsurf->base.MipmapTexture))
++ return EGL_FALSE;
++ gsurf->base.BoundToTexture = EGL_TRUE;
++ }
+
+ return EGL_TRUE;
+ }
+@@ -1158,9 +1063,10 @@ egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+
+ /* what if the context the surface binds to is no longer current? */
+- if (gctx)
+- gctx->stapi->st_unbind_texture_surface(gsurf->render_surface,
+- ST_TEXTURE_2D, gsurf->base.MipmapLevel);
++ if (gctx) {
++ gctx->stctxi->teximage(gctx->stctxi, ST_TEXTURE_2D,
++ gsurf->base.MipmapLevel, PIPE_FORMAT_NONE, NULL, FALSE);
++ }
+ }
+
+ gsurf->base.BoundToTexture = EGL_FALSE;
+@@ -1198,9 +1104,6 @@ egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
+ return NULL;
+ }
+
+- gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ?
+- NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
+-
+ return &gsurf->base;
+ }
+
+@@ -1294,6 +1197,12 @@ static void
+ egl_g3d_unload(_EGLDriver *drv)
+ {
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
++ EGLint i;
++
++ for (i = 0; i < ST_API_COUNT; i++) {
++ if (gdrv->stapis[i])
++ gdrv->stapis[i]->destroy(gdrv->stapis[i]);
++ }
+
+ egl_g3d_destroy_probe(drv, NULL);
+ free(gdrv);
+diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h
+index 3dae8c4..e2b73bb 100644
+--- a/src/gallium/state_trackers/egl/common/egl_g3d.h
++++ b/src/gallium/state_trackers/egl/common/egl_g3d.h
+@@ -38,11 +38,11 @@
+ #include "eglmode.h"
+
+ #include "native.h"
+-#include "egl_st.h"
++#include "egl_st_api.h"
+
+ struct egl_g3d_driver {
+ _EGLDriver base;
+- const struct egl_g3d_st *stapis[NUM_EGL_G3D_STS];
++ struct st_api *stapis[ST_API_COUNT];
+ EGLint api_mask;
+
+ EGLint probe_key;
+@@ -50,28 +50,27 @@ struct egl_g3d_driver {
+
+ struct egl_g3d_display {
+ struct native_display *native;
+-};
+
+-struct egl_g3d_buffer {
+- struct st_framebuffer *st_fb;
+- uint attachment_mask;
++ struct st_manager *smapi;
+ };
+
+ struct egl_g3d_context {
+ _EGLContext base;
+
+- const struct egl_g3d_st *stapi;
++ struct st_api *stapi;
+ struct pipe_context *pipe;
+
+- struct st_context *st_ctx;
++ struct st_context_iface *stctxi;
+ EGLBoolean force_validate;
+- struct egl_g3d_buffer draw, read;
+ };
+
+ struct egl_g3d_surface {
+ _EGLSurface base;
++
++ struct st_visual stvis;
++ struct st_framebuffer_iface *stfbi;
++
+ struct native_surface *native;
+- enum native_attachment render_att;
+ struct pipe_surface *render_surface;
+ unsigned int sequence_number;
+ };
+diff --git a/src/gallium/state_trackers/egl/common/egl_st.c b/src/gallium/state_trackers/egl/common/egl_st.c
+deleted file mode 100644
+index a88ff91..0000000
+--- a/src/gallium/state_trackers/egl/common/egl_st.c
++++ /dev/null
+@@ -1,131 +0,0 @@
+-/*
+- * Mesa 3-D graphics library
+- * Version: 7.8
+- *
+- * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+- *
+- * 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
+- * BRIAN PAUL 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.
+- */
+-
+-#include <dlfcn.h>
+-#include "pipe/p_compiler.h"
+-#include "util/u_memory.h"
+-#include "egllog.h"
+-#include "EGL/egl.h" /* for EGL_api_BIT */
+-
+-#include "egl_st.h"
+-
+-#ifndef HAVE_DLADDR
+-#define HAVE_DLADDR 1
+-#endif
+-
+-#if HAVE_DLADDR
+-
+-static const char *
+-egl_g3d_st_names[] = {
+-#define ST_PUBLIC(name, ...) #name,
+-#include "st_public_tmp.h"
+- NULL
+-};
+-
+-static boolean
+-egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
+-{
+- st_proc *procs = (st_proc *) stapi;
+- void *handle;
+- Dl_info info;
+- const char **name;
+-
+- if (!dladdr(sym, &info))
+- return FALSE;
+- handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE);
+- if (!handle)
+- return FALSE;
+-
+- for (name = egl_g3d_st_names; *name; name++) {
+- st_proc proc = (st_proc) dlsym(handle, *name);
+- if (!proc) {
+- _eglLog(_EGL_WARNING, "%s is missing in %s", *name, info.dli_fname);
+- memset(stapi, 0, sizeof(*stapi));
+- dlclose(handle);
+- return FALSE;
+- }
+- *procs++ = proc;
+- }
+-
+- dlclose(handle);
+- return TRUE;
+-}
+-
+-#else /* HAVE_DLADDR */
+-
+-static boolean
+-egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym)
+-{
+-#define ST_PUBLIC(name, ...) stapi->name = name;
+-#include "st_public_tmp.h"
+- return TRUE;
+-}
+-
+-#endif /* HAVE_DLADDR */
+-
+-static boolean
+-egl_g3d_init_st(struct egl_g3d_st *stapi, const char *api)
+-{
+- void *handle, *sym;
+- boolean res = FALSE;
+-
+- /* already initialized */
+- if (stapi->st_notify_swapbuffers != NULL)
+- return TRUE;
+-
+- handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL);
+- if (!handle)
+- return FALSE;
+-
+- sym = dlsym(handle, api);
+- if (sym && egl_g3d_fill_st(stapi, sym))
+- res = TRUE;
+-
+- dlclose(handle);
+- return res;
+-}
+-
+-static struct {
+- const char *symbol;
+- EGLint api_bit;
+-} egl_g3d_st_info[NUM_EGL_G3D_STS] = {
+- { "st_api_OpenGL_ES1", EGL_OPENGL_ES_BIT },
+- { "st_api_OpenVG", EGL_OPENVG_BIT },
+- { "st_api_OpenGL_ES2", EGL_OPENGL_ES2_BIT },
+- { "st_api_OpenGL", EGL_OPENGL_BIT },
+-};
+-
+-const struct egl_g3d_st *
+-egl_g3d_get_st(enum egl_g3d_st_api api)
+-{
+- static struct egl_g3d_st all_trackers[NUM_EGL_G3D_STS];
+-
+- if (egl_g3d_init_st(&all_trackers[api], egl_g3d_st_info[api].symbol)) {
+- all_trackers[api].api_bit = egl_g3d_st_info[api].api_bit;
+- return &all_trackers[api];
+- }
+- else {
+- return NULL;
+- }
+-}
+diff --git a/src/gallium/state_trackers/egl/common/egl_st.h b/src/gallium/state_trackers/egl/common/egl_st.h
+deleted file mode 100644
+index 8fb464b..0000000
+--- a/src/gallium/state_trackers/egl/common/egl_st.h
++++ /dev/null
+@@ -1,73 +0,0 @@
+-/*
+- * Mesa 3-D graphics library
+- * Version: 7.8
+- *
+- * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+- *
+- * 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
+- * BRIAN PAUL 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.
+- */
+-
+-#ifndef _EGL_ST_H_
+-#define _EGL_ST_H_
+-
+-#include "GL/gl.h" /* for GL types */
+-#include "GL/internal/glcore.h" /* for __GLcontextModes */
+-
+-#include "pipe/p_compiler.h"
+-#include "pipe/p_format.h"
+-#include "pipe/p_context.h"
+-
+-/* avoid calling st functions directly */
+-#if 1
+-
+-#define ST_SURFACE_FRONT_LEFT 0
+-#define ST_SURFACE_BACK_LEFT 1
+-#define ST_SURFACE_FRONT_RIGHT 2
+-#define ST_SURFACE_BACK_RIGHT 3
+-
+-#define ST_TEXTURE_2D 0x2
+-
+-struct st_context;
+-struct st_framebuffer;
+-typedef void (*st_proc)();
+-
+-#else
+-#include "state_tracker/st_public.h"
+-#endif
+-
+-/* remember to update egl_g3d_get_st() when update the enums */
+-enum egl_g3d_st_api {
+- EGL_G3D_ST_OPENGL_ES = 0,
+- EGL_G3D_ST_OPENVG,
+- EGL_G3D_ST_OPENGL_ES2,
+- EGL_G3D_ST_OPENGL,
+-
+- NUM_EGL_G3D_STS
+-};
+-
+-struct egl_g3d_st {
+-#define ST_PUBLIC(name, ret, ...) ret (*name)(__VA_ARGS__);
+-#include "st_public_tmp.h"
+- /* fields must be added here */
+- EGLint api_bit;
+-};
+-
+-const struct egl_g3d_st *
+-egl_g3d_get_st(enum egl_g3d_st_api api);
+-
+-#endif /* _EGL_ST_H_ */
+diff --git a/src/gallium/state_trackers/egl/common/st_public_tmp.h b/src/gallium/state_trackers/egl/common/st_public_tmp.h
+deleted file mode 100644
+index 507a0ec..0000000
+--- a/src/gallium/state_trackers/egl/common/st_public_tmp.h
++++ /dev/null
+@@ -1,20 +0,0 @@
+-ST_PUBLIC(st_create_context, struct st_context *, struct pipe_context *pipe, const __GLcontextModes *visual, struct st_context *share)
+-ST_PUBLIC(st_destroy_context, void, struct st_context *st)
+-ST_PUBLIC(st_copy_context_state, void, struct st_context *dst, struct st_context *src, uint mask)
+-ST_PUBLIC(st_create_framebuffer, struct st_framebuffer *, const __GLcontextModes *visual, enum pipe_format colorFormat, enum pipe_format depthFormat, enum pipe_format stencilFormat, uint width, uint height, void *privateData)
+-ST_PUBLIC(st_resize_framebuffer, void, struct st_framebuffer *stfb, uint width, uint height)
+-ST_PUBLIC(st_set_framebuffer_surface, void, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface *surf)
+-ST_PUBLIC(st_get_framebuffer_dimensions, void, struct st_framebuffer *stfb, uint *width, uint *height)
+-ST_PUBLIC(st_get_framebuffer_surface, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface)
+-ST_PUBLIC(st_get_framebuffer_texture, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture)
+-ST_PUBLIC(st_framebuffer_private, void *, struct st_framebuffer *stfb)
+-ST_PUBLIC(st_unreference_framebuffer, void, struct st_framebuffer *stfb)
+-ST_PUBLIC(st_make_current, GLboolean, struct st_context *st, struct st_framebuffer *draw, struct st_framebuffer *read)
+-ST_PUBLIC(st_get_current, struct st_context *, void)
+-ST_PUBLIC(st_flush, void, struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence)
+-ST_PUBLIC(st_finish, void, struct st_context *st)
+-ST_PUBLIC(st_notify_swapbuffers, void, struct st_framebuffer *stfb)
+-ST_PUBLIC(st_bind_texture_surface, int, struct pipe_surface *ps, int target, int level, enum pipe_format format)
+-ST_PUBLIC(st_unbind_texture_surface, int, struct pipe_surface *ps, int target, int level)
+-ST_PUBLIC(st_get_proc_address, st_proc, const char *procname)
+-#undef ST_PUBLIC
+--
+1.6.5
+