summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorChia-I Wu <[email protected]>2010-03-21 16:32:34 +0800
committerChia-I Wu <[email protected]>2010-03-21 16:32:34 +0800
commit12deb9e6ca76d222badf71c8643e84640673e86d (patch)
treeb11fef6689da399c661e8291d15ba938a6d88ab2 /src/gallium
parent162bc831c93bf8632b25c11f116a1405b93a1704 (diff)
parentfe5f070ef94219f12196bff6cb3274756ea03660 (diff)
Merge remote branch 'origin/gallium-st-api-dri'
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/state_trackers/dri/Makefile4
-rw-r--r--src/gallium/state_trackers/dri/SConscript2
-rw-r--r--src/gallium/state_trackers/dri/dri1.c583
-rw-r--r--src/gallium/state_trackers/dri/dri1.h63
-rw-r--r--src/gallium/state_trackers/dri/dri_context.c117
-rw-r--r--src/gallium/state_trackers/dri/dri_context.h33
-rw-r--r--src/gallium/state_trackers/dri/dri_drawable.c680
-rw-r--r--src/gallium/state_trackers/dri/dri_drawable.h39
-rw-r--r--src/gallium/state_trackers/dri/dri_extensions.c4
-rw-r--r--src/gallium/state_trackers/dri/dri_screen.c204
-rw-r--r--src/gallium/state_trackers/dri/dri_screen.h21
-rw-r--r--src/gallium/state_trackers/dri/dri_st_api.c445
-rw-r--r--src/gallium/state_trackers/dri/dri_st_api.h55
13 files changed, 1345 insertions, 905 deletions
diff --git a/src/gallium/state_trackers/dri/Makefile b/src/gallium/state_trackers/dri/Makefile
index ef8f19709ab..f5af8aa3a67 100644
--- a/src/gallium/state_trackers/dri/Makefile
+++ b/src/gallium/state_trackers/dri/Makefile
@@ -15,7 +15,9 @@ C_SOURCES = \
dri_context.c \
dri_screen.c \
dri_drawable.c \
- dri_extensions.c
+ dri_extensions.c \
+ dri_st_api.c \
+ dri1.c
# $(TOP)/src/mesa/drivers/dri/common/utils.c \
$(TOP)/src/mesa/drivers/dri/common/vblank.c \
diff --git a/src/gallium/state_trackers/dri/SConscript b/src/gallium/state_trackers/dri/SConscript
index ce2c2735974..7c67ceecd80 100644
--- a/src/gallium/state_trackers/dri/SConscript
+++ b/src/gallium/state_trackers/dri/SConscript
@@ -18,6 +18,8 @@ if env['dri']:
'dri_drawable.c',
'dri_extensions.c',
'dri_screen.c',
+ 'dri_st_api.c',
+ 'dri1.c',
]
)
Export('st_dri')
diff --git a/src/gallium/state_trackers/dri/dri1.c b/src/gallium/state_trackers/dri/dri1.c
new file mode 100644
index 00000000000..240bc69efd5
--- /dev/null
+++ b/src/gallium/state_trackers/dri/dri1.c
@@ -0,0 +1,583 @@
+/**************************************************************************
+ *
+ * Copyright 2009, 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+/*
+ * Author: Keith Whitwell <[email protected]>
+ * Author: Jakob Bornecrantz <[email protected]>
+ */
+
+/* XXX DRI1 is untested after the switch to st_api.h */
+
+#include "util/u_memory.h"
+#include "util/u_rect.h"
+#include "util/u_inlines.h"
+#include "pipe/p_context.h"
+#include "state_tracker/dri1_api.h"
+
+#include "dri_screen.h"
+#include "dri_context.h"
+#include "dri_drawable.h"
+#include "dri_st_api.h"
+#include "dri1.h"
+
+static INLINE void
+dri1_lock(struct dri_context *ctx)
+{
+ drm_context_t hw_context = ctx->cPriv->hHWContext;
+ char ret = 0;
+
+ DRM_CAS(ctx->lock, hw_context, DRM_LOCK_HELD | hw_context, ret);
+ if (ret) {
+ drmGetLock(ctx->sPriv->fd, hw_context, 0);
+ ctx->stLostLock = TRUE;
+ ctx->wsLostLock = TRUE;
+ }
+ ctx->isLocked = TRUE;
+}
+
+static INLINE void
+dri1_unlock(struct dri_context *ctx)
+{
+ ctx->isLocked = FALSE;
+ DRM_UNLOCK(ctx->sPriv->fd, ctx->lock, ctx->cPriv->hHWContext);
+}
+
+static struct pipe_fence_handle *
+dri_swap_fences_pop_front(struct dri_drawable *draw)
+{
+ struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
+ struct pipe_fence_handle *fence = NULL;
+
+ if (draw->cur_fences >= draw->desired_fences) {
+ screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]);
+ screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL);
+ --draw->cur_fences;
+ draw->tail &= DRI_SWAP_FENCES_MASK;
+ }
+ return fence;
+}
+
+static void
+dri_swap_fences_push_back(struct dri_drawable *draw,
+ struct pipe_fence_handle *fence)
+{
+ struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
+
+ if (!fence)
+ return;
+
+ if (draw->cur_fences < DRI_SWAP_FENCES_MAX) {
+ draw->cur_fences++;
+ screen->fence_reference(screen, &draw->swap_fences[draw->head++],
+ fence);
+ draw->head &= DRI_SWAP_FENCES_MASK;
+ }
+}
+
+void
+dri1_swap_fences_clear(struct dri_drawable *drawable)
+{
+ struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen;
+ struct pipe_fence_handle *fence;
+
+ while (drawable->cur_fences) {
+ fence = dri_swap_fences_pop_front(drawable);
+ screen->fence_reference(screen, &fence, NULL);
+ }
+}
+
+static void
+dri1_update_drawables_locked(struct dri_context *ctx,
+ __DRIdrawable * driDrawPriv,
+ __DRIdrawable * driReadPriv)
+{
+ if (ctx->stLostLock) {
+ ctx->stLostLock = FALSE;
+ if (driDrawPriv == driReadPriv)
+ DRI_VALIDATE_DRAWABLE_INFO(ctx->sPriv, driDrawPriv);
+ else
+ DRI_VALIDATE_TWO_DRAWABLES_INFO(ctx->sPriv, driDrawPriv,
+ driReadPriv);
+ }
+}
+
+/**
+ * This ensures all contexts which bind to a drawable pick up the
+ * drawable change and signal new buffer state.
+ */
+static void
+dri1_propagate_drawable_change(struct dri_context *ctx)
+{
+ __DRIdrawable *dPriv = ctx->dPriv;
+ __DRIdrawable *rPriv = ctx->rPriv;
+ struct dri_drawable *draw = dri_drawable(dPriv);
+ struct dri_drawable *read = dri_drawable(rPriv);
+ boolean flushed = FALSE;
+
+ if (dPriv && draw->texture_stamp != dPriv->lastStamp) {
+ ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ flushed = TRUE;
+ ctx->st->notify_invalid_framebuffer(ctx->st, draw->stfb);
+ }
+
+ if (rPriv && dPriv != rPriv && read->texture_stamp != rPriv->lastStamp) {
+ if (!flushed)
+ ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ ctx->st->notify_invalid_framebuffer(ctx->st, read->stfb);
+ }
+}
+
+static INLINE boolean
+dri1_intersect_src_bbox(struct drm_clip_rect *dst,
+ int dst_x,
+ int dst_y,
+ const struct drm_clip_rect *src,
+ const struct drm_clip_rect *bbox)
+{
+ int xy1;
+ int xy2;
+
+ xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 :
+ (int)bbox->x1 + dst_x;
+ xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 :
+ (int)bbox->x2 + dst_x;
+ if (xy1 >= xy2 || xy1 < 0)
+ return FALSE;
+
+ dst->x1 = xy1;
+ dst->x2 = xy2;
+
+ xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 :
+ (int)bbox->y1 + dst_y;
+ xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 :
+ (int)bbox->y2 + dst_y;
+ if (xy1 >= xy2 || xy1 < 0)
+ return FALSE;
+
+ dst->y1 = xy1;
+ dst->y2 = xy2;
+ return TRUE;
+}
+
+static void
+dri1_swap_copy(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ struct pipe_surface *src,
+ __DRIdrawable * dPriv, const struct drm_clip_rect *bbox)
+{
+ struct drm_clip_rect clip;
+ struct drm_clip_rect *cur;
+ int i;
+
+ cur = dPriv->pClipRects;
+
+ for (i = 0; i < dPriv->numClipRects; ++i) {
+ if (dri1_intersect_src_bbox(&clip, dPriv->x, dPriv->y, cur++, bbox)) {
+ if (pipe->surface_copy) {
+ pipe->surface_copy(pipe, dst, clip.x1, clip.y1,
+ src,
+ (int)clip.x1 - dPriv->x,
+ (int)clip.y1 - dPriv->y,
+ clip.x2 - clip.x1, clip.y2 - clip.y1);
+ } else {
+ util_surface_copy(pipe, FALSE, dst, clip.x1, clip.y1,
+ src,
+ (int)clip.x1 - dPriv->x,
+ (int)clip.y1 - dPriv->y,
+ clip.x2 - clip.x1, clip.y2 - clip.y1);
+ }
+ }
+ }
+}
+
+static struct pipe_surface *
+dri1_get_pipe_surface(struct dri_drawable *drawable, struct pipe_texture *ptex)
+{
+ struct pipe_screen *pipe_screen = dri_screen(drawable->sPriv)->pipe_screen;
+ struct pipe_surface *psurf = drawable->dri1_surface;
+
+ if (!psurf || psurf->texture != ptex) {
+ pipe_surface_reference(&drawable->dri1_surface, NULL);
+
+ drawable->dri1_surface = pipe_screen->get_tex_surface(pipe_screen,
+ ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ);
+
+ psurf = drawable->dri1_surface;
+ }
+
+ return psurf;
+}
+
+static struct pipe_context *
+dri1_get_pipe_context(struct dri_drawable *drawable)
+{
+ struct dri_screen *screen = dri_screen(drawable->sPriv);
+ struct pipe_context *pipe = screen->dri1_pipe;
+
+ if (!pipe) {
+ screen->dri1_pipe =
+ screen->pipe_screen->context_create(screen->pipe_screen, NULL);
+ pipe = screen->dri1_pipe;
+ }
+
+ return pipe;
+}
+
+static void
+dri1_present_texture_locked(__DRIdrawable * dPriv,
+ struct pipe_texture *ptex,
+ const struct drm_clip_rect *sub_box,
+ struct pipe_fence_handle **fence)
+{
+ struct dri_drawable *drawable = dri_drawable(dPriv);
+ struct pipe_context *pipe;
+ struct pipe_surface *psurf;
+ struct drm_clip_rect bbox;
+ boolean visible = TRUE;
+
+ *fence = NULL;
+
+ bbox.x1 = 0;
+ bbox.x2 = ptex->width0;
+ bbox.y1 = 0;
+ bbox.y2 = ptex->height0;
+
+ if (sub_box)
+ visible = dri1_intersect_src_bbox(&bbox, 0, 0, &bbox, sub_box);
+ if (!visible)
+ return;
+
+ pipe = dri1_get_pipe_context(drawable);
+ psurf = dri1_get_pipe_surface(drawable, ptex);
+ if (!pipe || !psurf)
+ return;
+
+ if (__dri1_api_hooks->present_locked) {
+ __dri1_api_hooks->present_locked(pipe, psurf,
+ dPriv->pClipRects, dPriv->numClipRects,
+ dPriv->x, dPriv->y, &bbox, fence);
+ } else if (__dri1_api_hooks->front_srf_locked) {
+ struct pipe_surface *front = __dri1_api_hooks->front_srf_locked(pipe);
+
+ if (front)
+ dri1_swap_copy(pipe, front, psurf, dPriv, &bbox);
+
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, fence);
+ }
+}
+
+static void
+dri1_copy_to_front(struct dri_context *ctx,
+ struct pipe_texture *ptex,
+ __DRIdrawable * dPriv,
+ const struct drm_clip_rect *sub_box,
+ struct pipe_fence_handle **fence)
+{
+ boolean save_lost_lock;
+
+ dri1_lock(ctx);
+ save_lost_lock = ctx->stLostLock;
+ dri1_update_drawables_locked(ctx, dPriv, dPriv);
+
+ dri1_present_texture_locked(dPriv, ptex, sub_box, fence);
+
+ ctx->stLostLock = save_lost_lock;
+
+ /**
+ * FIXME: Revisit this: Update drawables on copy_sub_buffer ?
+ */
+
+ if (!sub_box)
+ dri1_update_drawables_locked(ctx, ctx->dPriv, ctx->rPriv);
+
+ dri1_unlock(ctx);
+ dri1_propagate_drawable_change(ctx);
+}
+
+void
+dri1_flush_frontbuffer(struct dri_drawable *drawable,
+ struct pipe_texture *ptex)
+{
+ struct st_api *stapi = dri_get_st_api();
+ struct dri_screen *screen = dri_screen(drawable->sPriv);
+ struct pipe_screen *pipe_screen = screen->pipe_screen;
+ struct dri_context *ctx;
+ struct pipe_fence_handle *dummy_fence;
+ struct st_context_iface *st = stapi->get_current(stapi);
+
+ if (!st)
+ return;
+
+ ctx = (struct dri_context *) st->st_manager_private;
+
+ dri1_copy_to_front(ctx, ptex, ctx->dPriv, NULL, &dummy_fence);
+ pipe_screen->fence_reference(pipe_screen, &dummy_fence, NULL);
+
+ /**
+ * FIXME: Do we need swap throttling here?
+ */
+}
+
+void
+dri1_swap_buffers(__DRIdrawable * dPriv)
+{
+ struct dri_context *ctx = dri_get_current();
+ struct dri_drawable *draw = dri_drawable(dPriv);
+ struct dri_screen *screen = dri_screen(draw->sPriv);
+ struct pipe_screen *pipe_screen = screen->pipe_screen;
+ struct pipe_fence_handle *fence;
+ struct pipe_texture *ptex;
+
+ assert(__dri1_api_hooks != NULL);
+
+ if (!ctx)
+ return; /* For now */
+
+ ptex = draw->textures[ST_ATTACHMENT_BACK_LEFT];
+ if (ptex) {
+ ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ fence = dri_swap_fences_pop_front(draw);
+ if (fence) {
+ (void)pipe_screen->fence_finish(pipe_screen, fence, 0);
+ pipe_screen->fence_reference(pipe_screen, &fence, NULL);
+ }
+ dri1_copy_to_front(ctx, ptex, dPriv, NULL, &fence);
+ dri_swap_fences_push_back(draw, fence);
+ pipe_screen->fence_reference(pipe_screen, &fence, NULL);
+ }
+}
+
+void
+dri1_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h)
+{
+ struct dri_context *ctx = dri_get_current();
+ struct dri_screen *screen = dri_screen(dPriv->driScreenPriv);
+ struct pipe_screen *pipe_screen = screen->pipe_screen;
+ struct drm_clip_rect sub_bbox;
+ struct dri_drawable *draw = dri_drawable(dPriv);
+ struct pipe_fence_handle *dummy_fence;
+ struct pipe_texture *ptex;
+
+ assert(__dri1_api_hooks != NULL);
+
+ if (!ctx)
+ return;
+
+ sub_bbox.x1 = x;
+ sub_bbox.x2 = x + w;
+ sub_bbox.y1 = y;
+ sub_bbox.y2 = y + h;
+
+ ptex = draw->textures[ST_ATTACHMENT_BACK_LEFT];
+ if (ptex) {
+ ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ dri1_copy_to_front(ctx, ptex, dPriv, &sub_bbox, &dummy_fence);
+ pipe_screen->fence_reference(pipe_screen, &dummy_fence, NULL);
+ }
+}
+
+void
+dri1_allocate_textures(struct dri_drawable *drawable,
+ unsigned width, unsigned height,
+ unsigned mask)
+{
+ struct dri_screen *screen = dri_screen(drawable->sPriv);
+ struct pipe_texture templ;
+ int i;
+
+ /* remove outdated textures */
+ if (drawable->old_w != width || drawable->old_h != height) {
+ for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
+ pipe_texture_reference(&drawable->textures[i], NULL);
+ }
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.width0 = width;
+ templ.height0 = height;
+ templ.depth0 = 1;
+ templ.last_level = 0;
+
+ for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
+ enum pipe_format format;
+ unsigned tex_usage;
+
+ /* the texture already exists or not requested */
+ if (drawable->textures[i] || !(mask & (1 << i))) {
+ /* remember the texture */
+ if (drawable->textures[i])
+ mask |= (1 << i);
+ continue;
+ }
+
+ switch (i) {
+ case ST_ATTACHMENT_FRONT_LEFT:
+ case ST_ATTACHMENT_BACK_LEFT:
+ case ST_ATTACHMENT_FRONT_RIGHT:
+ case ST_ATTACHMENT_BACK_RIGHT:
+ format = drawable->stvis.color_format;
+ tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ break;
+ case ST_ATTACHMENT_DEPTH_STENCIL:
+ format = drawable->stvis.depth_stencil_format;
+ tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+ break;
+ default:
+ format = PIPE_FORMAT_NONE;
+ break;
+ }
+
+ if (format != PIPE_FORMAT_NONE) {
+ templ.format = format;
+ templ.tex_usage = tex_usage;
+
+ drawable->textures[i] =
+ screen->pipe_screen->texture_create(screen->pipe_screen, &templ);
+ }
+ }
+
+ drawable->old_w = width;
+ drawable->old_h = height;
+ drawable->texture_mask = mask;
+}
+
+static void
+st_dri_lock(struct pipe_context *pipe)
+{
+ dri1_lock((struct dri_context *)pipe->priv);
+}
+
+static void
+st_dri_unlock(struct pipe_context *pipe)
+{
+ dri1_unlock((struct dri_context *)pipe->priv);
+}
+
+static boolean
+st_dri_is_locked(struct pipe_context *pipe)
+{
+ return ((struct dri_context *)pipe->priv)->isLocked;
+}
+
+static boolean
+st_dri_lost_lock(struct pipe_context *pipe)
+{
+ return ((struct dri_context *)pipe->priv)->wsLostLock;
+}
+
+static void
+st_dri_clear_lost_lock(struct pipe_context *pipe)
+{
+ ((struct dri_context *)pipe->priv)->wsLostLock = FALSE;
+}
+
+static struct dri1_api_lock_funcs dri1_lf = {
+ .lock = st_dri_lock,
+ .unlock = st_dri_unlock,
+ .is_locked = st_dri_is_locked,
+ .is_lock_lost = st_dri_lost_lock,
+ .clear_lost_lock = st_dri_clear_lost_lock
+};
+
+static const __DRIextension *dri1_screen_extensions[] = {
+ &driReadDrawableExtension,
+ &driCopySubBufferExtension.base,
+ &driSwapControlExtension.base,
+ &driFrameTrackingExtension.base,
+ &driMediaStreamCounterExtension.base,
+ NULL
+};
+
+struct dri1_api *__dri1_api_hooks = NULL;
+
+static INLINE void
+dri1_copy_version(struct dri1_api_version *dst,
+ const struct __DRIversionRec *src)
+{
+ dst->major = src->major;
+ dst->minor = src->minor;
+ dst->patch_level = src->patch;
+}
+
+const __DRIconfig **
+dri1_init_screen(__DRIscreen * sPriv)
+{
+ struct dri_screen *screen;
+ const __DRIconfig **configs;
+ struct dri1_create_screen_arg arg;
+
+ screen = CALLOC_STRUCT(dri_screen);
+ if (!screen)
+ return NULL;
+
+ screen->api = drm_api_create();
+ screen->sPriv = sPriv;
+ screen->fd = sPriv->fd;
+ screen->drmLock = (drmLock *) & sPriv->pSAREA->lock;
+
+ sPriv->private = (void *)screen;
+ sPriv->extensions = dri1_screen_extensions;
+
+ arg.base.mode = DRM_CREATE_DRI1;
+ arg.lf = &dri1_lf;
+ arg.ddx_info = sPriv->pDevPriv;
+ arg.ddx_info_size = sPriv->devPrivSize;
+ arg.sarea = sPriv->pSAREA;
+ dri1_copy_version(&arg.ddx_version, &sPriv->ddx_version);
+ dri1_copy_version(&arg.dri_version, &sPriv->dri_version);
+ dri1_copy_version(&arg.drm_version, &sPriv->drm_version);
+ arg.api = NULL;
+
+ screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg.base);
+
+ if (!screen->pipe_screen || !arg.api) {
+ debug_printf("%s: failed to create dri1 screen\n", __FUNCTION__);
+ goto out_no_screen;
+ }
+
+ __dri1_api_hooks = arg.api;
+
+ driParseOptionInfo(&screen->optionCache,
+ __driConfigOptions, __driNConfigOptions);
+
+ /**
+ * FIXME: If the driver supports format conversion swapbuffer blits, we might
+ * want to support other color bit depths than the server is currently
+ * using.
+ */
+
+ configs = dri_fill_in_modes(screen, sPriv->fbBPP);
+ if (!configs)
+ goto out_no_configs;
+
+ return configs;
+ out_no_configs:
+ screen->pipe_screen->destroy(screen->pipe_screen);
+ out_no_screen:
+ FREE(screen);
+ return NULL;
+}
diff --git a/src/gallium/state_trackers/dri/dri1.h b/src/gallium/state_trackers/dri/dri1.h
new file mode 100644
index 00000000000..e83571e57be
--- /dev/null
+++ b/src/gallium/state_trackers/dri/dri1.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+ *
+ * Copyright 2009, 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+/*
+ * Author: Keith Whitwell <[email protected]>
+ * Author: Jakob Bornecrantz <[email protected]>
+ */
+
+#ifndef DRI1_H
+#define DRI1_H
+
+#include "dri_context.h"
+#include "dri_drawable.h"
+
+#include "state_tracker/st_api.h"
+#include "dri_util.h"
+
+extern struct dri1_api *__dri1_api_hooks;
+
+const __DRIconfig **
+dri1_init_screen(__DRIscreen * sPriv);
+
+void
+dri1_flush_frontbuffer(struct dri_drawable *drawable,
+ struct pipe_texture *ptex);
+
+void
+dri1_allocate_textures(struct dri_drawable *drawable,
+ unsigned width, unsigned height,
+ unsigned mask);
+
+void dri1_swap_buffers(__DRIdrawable * dPriv);
+
+void
+dri1_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h);
+
+void
+dri1_swap_fences_clear(struct dri_drawable *drawable);
+
+#endif /* DRI1_H */
diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c
index f772ba5d16b..54568a8b220 100644
--- a/src/gallium/state_trackers/dri/dri_context.c
+++ b/src/gallium/state_trackers/dri/dri_context.c
@@ -30,25 +30,24 @@
*/
#include "dri_screen.h"
-
#include "dri_drawable.h"
-#include "state_tracker/drm_api.h"
-#include "state_tracker/dri1_api.h"
-#include "state_tracker/st_public.h"
-#include "pipe/p_context.h"
-
#include "dri_context.h"
+#include "dri_st_api.h"
+#include "dri1.h"
+#include "pipe/p_context.h"
#include "util/u_memory.h"
GLboolean
dri_create_context(const __GLcontextModes * visual,
__DRIcontext * cPriv, void *sharedContextPrivate)
{
+ struct st_api *stapi = dri_get_st_api();
__DRIscreen *sPriv = cPriv->driScreenPriv;
struct dri_screen *screen = dri_screen(sPriv);
struct dri_context *ctx = NULL;
- struct st_context *st_share = NULL;
+ struct st_context_iface *st_share = NULL;
+ struct st_visual stvis;
if (sharedContextPrivate) {
st_share = ((struct dri_context *)sharedContextPrivate)->st;
@@ -62,21 +61,15 @@ dri_create_context(const __GLcontextModes * visual,
ctx->cPriv = cPriv;
ctx->sPriv = sPriv;
ctx->lock = screen->drmLock;
- ctx->d_stamp = -1;
- ctx->r_stamp = -1;
driParseConfigFiles(&ctx->optionCache,
&screen->optionCache, sPriv->myNum, "dri");
- ctx->pipe = screen->pipe_screen->context_create( screen->pipe_screen,
- ctx );
-
- if (ctx->pipe == NULL)
- goto fail;
-
- ctx->st = st_create_context(ctx->pipe, visual, st_share);
+ dri_fill_st_visual(&stvis, screen, visual);
+ ctx->st = stapi->create_context(stapi, screen->smapi, &stvis, st_share);
if (ctx->st == NULL)
goto fail;
+ ctx->st->st_manager_private = (void *) ctx;
dri_init_extensions(ctx);
@@ -84,10 +77,7 @@ dri_create_context(const __GLcontextModes * visual,
fail:
if (ctx && ctx->st)
- st_destroy_context(ctx->st);
-
- if (ctx && ctx->pipe)
- ctx->pipe->destroy(ctx->pipe);
+ ctx->st->destroy(ctx->st);
FREE(ctx);
return FALSE;
@@ -109,11 +99,8 @@ dri_destroy_context(__DRIcontext * cPriv)
* to avoid having to add code elsewhere to cope with flushing a
* partially destroyed context.
*/
- st_flush(ctx->st, 0, NULL);
-
- /* Also frees ctx->pipe?
- */
- st_destroy_context(ctx->st);
+ ctx->st->flush(ctx->st, 0, NULL);
+ ctx->st->destroy(ctx->st);
FREE(ctx);
}
@@ -121,14 +108,16 @@ dri_destroy_context(__DRIcontext * cPriv)
GLboolean
dri_unbind_context(__DRIcontext * cPriv)
{
+ struct st_api *stapi = dri_get_st_api();
+
if (cPriv) {
struct dri_context *ctx = dri_context(cPriv);
if (--ctx->bind_count == 0) {
- if (ctx->st && ctx->st == st_get_current()) {
- st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
- st_make_current(NULL, NULL, NULL, NULL);
- }
+ if (ctx->st == stapi->get_current(stapi)) {
+ ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ stapi->make_current(stapi, NULL, NULL, NULL);
+ }
}
}
@@ -140,83 +129,47 @@ dri_make_current(__DRIcontext * cPriv,
__DRIdrawable * driDrawPriv,
__DRIdrawable * driReadPriv)
{
+ struct st_api *stapi = dri_get_st_api();
+
if (cPriv) {
struct dri_context *ctx = dri_context(cPriv);
struct dri_drawable *draw = dri_drawable(driDrawPriv);
struct dri_drawable *read = dri_drawable(driReadPriv);
- struct st_context *old_st = st_get_current();
+ struct st_context_iface *old_st;
+ old_st = stapi->get_current(stapi);
if (old_st && old_st != ctx->st)
- st_flush(old_st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ ctx->st->flush(old_st, PIPE_FLUSH_RENDER_CACHE, NULL);
++ctx->bind_count;
if (ctx->dPriv != driDrawPriv) {
ctx->dPriv = driDrawPriv;
- ctx->d_stamp = driDrawPriv->lastStamp - 1;
+ draw->texture_stamp = driDrawPriv->lastStamp - 1;
}
if (ctx->rPriv != driReadPriv) {
ctx->rPriv = driReadPriv;
- ctx->r_stamp = driReadPriv->lastStamp - 1;
+ read->texture_stamp = driReadPriv->lastStamp - 1;
}
- /* DRI co-state tracker currently overrides flush_frontbuffer.
- * When this is fixed, will need to pass the drawable in the
- * fourth parameter here so that when Mesa calls
- * flush_frontbuffer directly (in front-buffer rendering), it
- * will have access to the drawable argument:
- */
- st_make_current(ctx->st, draw->stfb, read->stfb, ctx);
-
- if (__dri1_api_hooks) {
- dri1_update_drawables(ctx, draw, read);
- } else {
- dri_update_buffer(ctx->pipe->screen,
- ctx->pipe->priv);
- }
- } else {
- st_make_current(NULL, NULL, NULL, NULL);
+ stapi->make_current(stapi, ctx->st, draw->stfb, read->stfb);
+ }
+ else {
+ stapi->make_current(stapi, NULL, NULL, NULL);
}
return GL_TRUE;
}
-static void
-st_dri_lock(struct pipe_context *pipe)
-{
- dri_lock((struct dri_context *)pipe->priv);
-}
-
-static void
-st_dri_unlock(struct pipe_context *pipe)
-{
- dri_unlock((struct dri_context *)pipe->priv);
-}
-
-static boolean
-st_dri_is_locked(struct pipe_context *pipe)
+struct dri_context *
+dri_get_current(void)
{
- return ((struct dri_context *)pipe->priv)->isLocked;
-}
+ struct st_api *stapi = dri_get_st_api();
+ struct st_context_iface *st;
-static boolean
-st_dri_lost_lock(struct pipe_context *pipe)
-{
- return ((struct dri_context *)pipe->priv)->wsLostLock;
-}
+ st = stapi->get_current(stapi);
-static void
-st_dri_clear_lost_lock(struct pipe_context *pipe)
-{
- ((struct dri_context *)pipe->priv)->wsLostLock = FALSE;
+ return (struct dri_context *) (st) ? st->st_manager_private : NULL;
}
-struct dri1_api_lock_funcs dri1_lf = {
- .lock = st_dri_lock,
- .unlock = st_dri_unlock,
- .is_locked = st_dri_is_locked,
- .is_lock_lost = st_dri_lost_lock,
- .clear_lost_lock = st_dri_clear_lost_lock
-};
-
/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_context.h b/src/gallium/state_trackers/dri/dri_context.h
index 13f497462f7..845b420cf89 100644
--- a/src/gallium/state_trackers/dri/dri_context.h
+++ b/src/gallium/state_trackers/dri/dri_context.h
@@ -51,9 +51,6 @@ struct dri_context
driOptionCache optionCache;
- unsigned int d_stamp;
- unsigned int r_stamp;
-
drmLock *lock;
boolean isLocked;
boolean stLostLock;
@@ -62,8 +59,7 @@ struct dri_context
unsigned int bind_count;
/* gallium */
- struct st_context *st;
- struct pipe_context *pipe;
+ struct st_context_iface *st;
};
static INLINE struct dri_context *
@@ -72,33 +68,9 @@ dri_context(__DRIcontext * driContextPriv)
return (struct dri_context *)driContextPriv->driverPrivate;
}
-static INLINE void
-dri_lock(struct dri_context *ctx)
-{
- drm_context_t hw_context = ctx->cPriv->hHWContext;
- char ret = 0;
-
- DRM_CAS(ctx->lock, hw_context, DRM_LOCK_HELD | hw_context, ret);
- if (ret) {
- drmGetLock(ctx->sPriv->fd, hw_context, 0);
- ctx->stLostLock = TRUE;
- ctx->wsLostLock = TRUE;
- }
- ctx->isLocked = TRUE;
-}
-
-static INLINE void
-dri_unlock(struct dri_context *ctx)
-{
- ctx->isLocked = FALSE;
- DRM_UNLOCK(ctx->sPriv->fd, ctx->lock, ctx->cPriv->hHWContext);
-}
-
/***********************************************************************
* dri_context.c
*/
-extern struct dri1_api_lock_funcs dri1_lf;
-
void dri_destroy_context(__DRIcontext * driContextPriv);
boolean dri_unbind_context(__DRIcontext * driContextPriv);
@@ -108,6 +80,9 @@ dri_make_current(__DRIcontext * driContextPriv,
__DRIdrawable * driDrawPriv,
__DRIdrawable * driReadPriv);
+struct dri_context *
+dri_get_current(void);
+
boolean
dri_create_context(const __GLcontextModes * visual,
__DRIcontext * driContextPriv,
diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c
index c400725c7f2..930387f8a67 100644
--- a/src/gallium/state_trackers/dri/dri_drawable.c
+++ b/src/gallium/state_trackers/dri/dri_drawable.c
@@ -32,251 +32,30 @@
#include "dri_screen.h"
#include "dri_context.h"
#include "dri_drawable.h"
+#include "dri_st_api.h"
+#include "dri1.h"
-#include "pipe/p_context.h"
#include "pipe/p_screen.h"
-#include "main/mtypes.h"
-#include "main/renderbuffer.h"
-#include "state_tracker/drm_api.h"
-#include "state_tracker/dri1_api.h"
-#include "state_tracker/st_context.h"
-#include "state_tracker/st_public.h"
-#include "state_tracker/st_cb_fbo.h"
-
#include "util/u_format.h"
#include "util/u_memory.h"
-#include "util/u_rect.h"
#include "util/u_inlines.h"
-static struct pipe_surface *
-dri_surface_from_handle(struct drm_api *api,
- struct pipe_screen *screen,
- unsigned handle,
- enum pipe_format format,
- unsigned width, unsigned height, unsigned pitch)
-{
- struct pipe_surface *surface = NULL;
- struct pipe_texture *texture = NULL;
- struct pipe_texture templat;
- struct winsys_handle whandle;
-
- memset(&templat, 0, sizeof(templat));
- templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
- templat.target = PIPE_TEXTURE_2D;
- templat.last_level = 0;
- templat.depth0 = 1;
- templat.format = format;
- templat.width0 = width;
- templat.height0 = height;
-
- memset(&whandle, 0, sizeof(whandle));
- whandle.handle = handle;
- whandle.stride = pitch;
-
- texture = screen->texture_from_handle(screen, &templat, &whandle);
-
- if (!texture) {
- debug_printf("%s: Failed to blanket the buffer with a texture\n", __func__);
- return NULL;
- }
-
- surface = screen->get_tex_surface(screen, texture, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_READ |
- PIPE_BUFFER_USAGE_GPU_WRITE);
-
- /* we don't need the texture from this point on */
- pipe_texture_reference(&texture, NULL);
- return surface;
-}
-
-/**
- * Pixmaps have will have the same name of fake front and front.
- */
-static boolean
-dri2_check_if_pixmap(__DRIbuffer *buffers, int count)
-{
- boolean found = FALSE;
- boolean is_pixmap = FALSE;
- unsigned name;
- int i;
-
- for (i = 0; i < count; i++) {
- switch (buffers[i].attachment) {
- case __DRI_BUFFER_FRONT_LEFT:
- case __DRI_BUFFER_FAKE_FRONT_LEFT:
- if (found) {
- is_pixmap = buffers[i].name == name;
- } else {
- name = buffers[i].name;
- found = TRUE;
- }
- default:
- continue;
- }
- }
-
- return is_pixmap;
-}
-
-/**
- * This will be called a drawable is known to have been resized.
- */
-void
-dri_get_buffers(__DRIdrawable * dPriv)
-{
-
- struct dri_drawable *drawable = dri_drawable(dPriv);
- struct pipe_surface *surface = NULL;
- struct dri_screen *st_screen = dri_screen(drawable->sPriv);
- struct pipe_screen *screen = st_screen->pipe_screen;
- __DRIbuffer *buffers = NULL;
- __DRIscreen *dri_screen = drawable->sPriv;
- __DRIdrawable *dri_drawable = drawable->dPriv;
- struct drm_api *api = st_screen->api;
- boolean have_depth = FALSE;
- int i, count;
-
- if ((dri_screen->dri2.loader
- && (dri_screen->dri2.loader->base.version > 2)
- && (dri_screen->dri2.loader->getBuffersWithFormat != NULL))) {
- buffers = (*dri_screen->dri2.loader->getBuffersWithFormat)
- (dri_drawable, &dri_drawable->w, &dri_drawable->h,
- drawable->attachments, drawable->num_attachments,
- &count, dri_drawable->loaderPrivate);
- } else {
- assert(dri_screen->dri2.loader);
- buffers = (*dri_screen->dri2.loader->getBuffers) (dri_drawable,
- &dri_drawable->w,
- &dri_drawable->h,
- drawable->attachments,
- drawable->
- num_attachments, &count,
- dri_drawable->
- loaderPrivate);
- }
-
- if (buffers == NULL) {
- return;
- }
-
- /* set one cliprect to cover the whole dri_drawable */
- dri_drawable->x = 0;
- dri_drawable->y = 0;
- dri_drawable->backX = 0;
- dri_drawable->backY = 0;
- dri_drawable->numClipRects = 1;
- dri_drawable->pClipRects[0].x1 = 0;
- dri_drawable->pClipRects[0].y1 = 0;
- dri_drawable->pClipRects[0].x2 = dri_drawable->w;
- dri_drawable->pClipRects[0].y2 = dri_drawable->h;
- dri_drawable->numBackClipRects = 1;
- dri_drawable->pBackClipRects[0].x1 = 0;
- dri_drawable->pBackClipRects[0].y1 = 0;
- dri_drawable->pBackClipRects[0].x2 = dri_drawable->w;
- dri_drawable->pBackClipRects[0].y2 = dri_drawable->h;
-
- if (drawable->old_num == count &&
- drawable->old_w == dri_drawable->w &&
- drawable->old_h == dri_drawable->h &&
- memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0) {
- return;
- } else {
- drawable->old_num = count;
- drawable->old_w = dri_drawable->w;
- drawable->old_h = dri_drawable->h;
- memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count);
- }
-
- drawable->is_pixmap = dri2_check_if_pixmap(buffers, count);
-
- for (i = 0; i < count; i++) {
- enum pipe_format format = 0;
- int index = 0;
-
- switch (buffers[i].attachment) {
- case __DRI_BUFFER_FRONT_LEFT:
- if (!st_screen->auto_fake_front)
- continue;
- /* fallthrough */
- case __DRI_BUFFER_FAKE_FRONT_LEFT:
- index = ST_SURFACE_FRONT_LEFT;
- format = drawable->color_format;
- break;
- case __DRI_BUFFER_BACK_LEFT:
- index = ST_SURFACE_BACK_LEFT;
- format = drawable->color_format;
- break;
- case __DRI_BUFFER_DEPTH:
- case __DRI_BUFFER_DEPTH_STENCIL:
- case __DRI_BUFFER_STENCIL:
- index = ST_SURFACE_DEPTH;
- format = drawable->depth_stencil_format;
- break;
- case __DRI_BUFFER_ACCUM:
- default:
- assert(0);
- }
-
- if (index == ST_SURFACE_DEPTH) {
- if (have_depth)
- continue;
- else
- have_depth = TRUE;
- }
-
- surface = dri_surface_from_handle(api,
- screen,
- buffers[i].name,
- format,
- dri_drawable->w,
- dri_drawable->h, buffers[i].pitch);
-
- switch (buffers[i].attachment) {
- case __DRI_BUFFER_FRONT_LEFT:
- case __DRI_BUFFER_FAKE_FRONT_LEFT:
- case __DRI_BUFFER_BACK_LEFT:
- drawable->color_format = surface->format;
- break;
- case __DRI_BUFFER_DEPTH:
- case __DRI_BUFFER_DEPTH_STENCIL:
- case __DRI_BUFFER_STENCIL:
- drawable->depth_stencil_format = surface->format;
- break;
- case __DRI_BUFFER_ACCUM:
- default:
- assert(0);
- }
-
- st_set_framebuffer_surface(drawable->stfb, index, surface);
- pipe_surface_reference(&surface, NULL);
- }
- /* this needed, or else the state tracker fails to pick the new buffers */
- st_resize_framebuffer(drawable->stfb, dri_drawable->w, dri_drawable->h);
-}
-
/**
* These are used for GLX_EXT_texture_from_pixmap
*/
void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
GLint format, __DRIdrawable *dPriv)
{
+ struct dri_context *ctx = dri_context(pDRICtx);
struct dri_drawable *drawable = dri_drawable(dPriv);
- struct pipe_surface *ps;
+ struct pipe_texture *pt =
+ dri_get_st_framebuffer_texture(drawable->stfb, ST_ATTACHMENT_FRONT_LEFT);
- if (!drawable->stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer) {
- struct gl_renderbuffer *rb =
- st_new_renderbuffer_fb(drawable->color_format, 0 /*XXX*/, FALSE);
- _mesa_add_renderbuffer(&drawable->stfb->Base, BUFFER_FRONT_LEFT, rb);
+ if (pt) {
+ ctx->st->teximage(ctx->st,
+ (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT,
+ 0, drawable->stvis.color_format, pt, FALSE);
}
-
- dri_get_buffers(drawable->dPriv);
- st_get_framebuffer_surface(drawable->stfb, ST_SURFACE_FRONT_LEFT, &ps);
-
- if (!ps)
- return;
-
- st_bind_texture_surface(ps, target == GL_TEXTURE_2D ? ST_TEXTURE_2D :
- ST_TEXTURE_RECT, 0, drawable->color_format);
}
void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target,
@@ -285,53 +64,6 @@ void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target,
dri2_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
}
-void
-dri_update_buffer(struct pipe_screen *screen, void *context_private)
-{
- struct dri_context *ctx = (struct dri_context *)context_private;
-
- if (ctx->d_stamp == *ctx->dPriv->pStamp &&
- ctx->r_stamp == *ctx->rPriv->pStamp)
- return;
-
- ctx->d_stamp = *ctx->dPriv->pStamp;
- ctx->r_stamp = *ctx->rPriv->pStamp;
-
- /* Ask the X server for new renderbuffers. */
- dri_get_buffers(ctx->dPriv);
- if (ctx->dPriv != ctx->rPriv)
- dri_get_buffers(ctx->rPriv);
-
-}
-
-void
-dri_flush_frontbuffer(struct pipe_screen *screen,
- struct pipe_surface *surf, void *context_private)
-{
- struct dri_context *ctx = (struct dri_context *)context_private;
- struct dri_drawable *drawable = dri_drawable(ctx->dPriv);
- __DRIdrawable *dri_drawable = ctx->dPriv;
- __DRIscreen *dri_screen = ctx->sPriv;
-
- /* XXX Does this function get called with DRI1? */
-
- if (ctx->dPriv == NULL) {
- debug_printf("%s: no drawable bound to context\n", __func__);
- return;
- }
-
-#if 0
- /* TODO if rendering to pixmaps is slow enable this code. */
- if (drawable->is_pixmap)
- return;
-#else
- (void)drawable;
-#endif
-
- (*dri_screen->dri2.loader->flushFrontBuffer)(dri_drawable,
- dri_drawable->loaderPrivate);
-}
-
/**
* This is called when we need to set up GL rendering to a new X window.
*/
@@ -342,7 +74,6 @@ dri_create_buffer(__DRIscreen * sPriv,
{
struct dri_screen *screen = sPriv->private;
struct dri_drawable *drawable = NULL;
- int i;
if (isPixmap)
goto fail; /* not implemented */
@@ -351,45 +82,8 @@ dri_create_buffer(__DRIscreen * sPriv,
if (drawable == NULL)
goto fail;
- if (visual->redBits == 8) {
- if (visual->alphaBits == 8)
- drawable->color_format = PIPE_FORMAT_B8G8R8A8_UNORM;
- else
- drawable->color_format = PIPE_FORMAT_B8G8R8X8_UNORM;
- } else {
- drawable->color_format = PIPE_FORMAT_B5G6R5_UNORM;
- }
-
- switch(visual->depthBits) {
- default:
- case 0:
- drawable->depth_stencil_format = PIPE_FORMAT_NONE;
- break;
- case 16:
- drawable->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
- break;
- case 24:
- if (visual->stencilBits == 0) {
- drawable->depth_stencil_format = (screen->d_depth_bits_last) ?
- PIPE_FORMAT_Z24X8_UNORM:
- PIPE_FORMAT_X8Z24_UNORM;
- } else {
- drawable->depth_stencil_format = (screen->sd_depth_bits_last) ?
- PIPE_FORMAT_Z24S8_UNORM:
- PIPE_FORMAT_S8Z24_UNORM;
- }
- break;
- case 32:
- drawable->depth_stencil_format = PIPE_FORMAT_Z32_UNORM;
- break;
- }
-
- drawable->stfb = st_create_framebuffer(visual,
- drawable->color_format,
- drawable->depth_stencil_format,
- drawable->depth_stencil_format,
- dPriv->w,
- dPriv->h, (void *)drawable);
+ dri_fill_st_visual(&drawable->stvis, screen, visual);
+ drawable->stfb = dri_create_st_framebuffer(drawable);
if (drawable->stfb == NULL)
goto fail;
@@ -397,48 +91,6 @@ dri_create_buffer(__DRIscreen * sPriv,
drawable->dPriv = dPriv;
dPriv->driverPrivate = (void *)drawable;
- /* setup dri2 buffers information */
- /* TODO incase of double buffer visual, delay fake creation */
- i = 0;
- if (sPriv->dri2.loader
- && (sPriv->dri2.loader->base.version > 2)
- && (sPriv->dri2.loader->getBuffersWithFormat != NULL)) {
- drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
- drawable->attachments[i++] = visual->rgbBits;
- if (!screen->auto_fake_front) {
- drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT;
- drawable->attachments[i++] = visual->rgbBits;
- }
- if (visual->doubleBufferMode) {
- drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT;
- drawable->attachments[i++] = visual->rgbBits;
- }
- if (visual->depthBits && visual->stencilBits) {
- drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
- drawable->attachments[i++] = visual->depthBits + visual->stencilBits;
- } else if (visual->depthBits) {
- drawable->attachments[i++] = __DRI_BUFFER_DEPTH;
- drawable->attachments[i++] = visual->depthBits;
- } else if (visual->stencilBits) {
- drawable->attachments[i++] = __DRI_BUFFER_STENCIL;
- drawable->attachments[i++] = visual->stencilBits;
- }
- drawable->num_attachments = i / 2;
- } else {
- drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
- if (!screen->auto_fake_front)
- drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT;
- if (visual->doubleBufferMode)
- drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT;
- if (visual->depthBits && visual->stencilBits)
- drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
- else if (visual->depthBits)
- drawable->attachments[i++] = __DRI_BUFFER_DEPTH;
- else if (visual->stencilBits)
- drawable->attachments[i++] = __DRI_BUFFER_STENCIL;
- drawable->num_attachments = i;
- }
-
drawable->desired_fences = 2;
return GL_TRUE;
@@ -447,319 +99,23 @@ fail:
return GL_FALSE;
}
-static struct pipe_fence_handle *
-dri_swap_fences_pop_front(struct dri_drawable *draw)
-{
- struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
- struct pipe_fence_handle *fence = NULL;
-
- if (draw->cur_fences >= draw->desired_fences) {
- screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]);
- screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL);
- --draw->cur_fences;
- draw->tail &= DRI_SWAP_FENCES_MASK;
- }
- return fence;
-}
-
-static void
-dri_swap_fences_push_back(struct dri_drawable *draw,
- struct pipe_fence_handle *fence)
-{
- struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
-
- if (!fence)
- return;
-
- if (draw->cur_fences < DRI_SWAP_FENCES_MAX) {
- draw->cur_fences++;
- screen->fence_reference(screen, &draw->swap_fences[draw->head++],
- fence);
- draw->head &= DRI_SWAP_FENCES_MASK;
- }
-}
-
void
dri_destroy_buffer(__DRIdrawable * dPriv)
{
struct dri_drawable *drawable = dri_drawable(dPriv);
- struct pipe_fence_handle *fence;
- struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen;
-
- st_unreference_framebuffer(drawable->stfb);
- drawable->desired_fences = 0;
- while (drawable->cur_fences) {
- fence = dri_swap_fences_pop_front(drawable);
- screen->fence_reference(screen, &fence, NULL);
- }
-
- FREE(drawable);
-}
-
-static void
-dri1_update_drawables_locked(struct dri_context *ctx,
- __DRIdrawable * driDrawPriv,
- __DRIdrawable * driReadPriv)
-{
- if (ctx->stLostLock) {
- ctx->stLostLock = FALSE;
- if (driDrawPriv == driReadPriv)
- DRI_VALIDATE_DRAWABLE_INFO(ctx->sPriv, driDrawPriv);
- else
- DRI_VALIDATE_TWO_DRAWABLES_INFO(ctx->sPriv, driDrawPriv,
- driReadPriv);
- }
-}
-
-/**
- * This ensures all contexts which bind to a drawable pick up the
- * drawable change and signal new buffer state.
- * Calling st_resize_framebuffer for each context may seem like overkill,
- * but no new buffers will actually be allocated if the dimensions don't
- * change.
- */
-
-static void
-dri1_propagate_drawable_change(struct dri_context *ctx)
-{
- __DRIdrawable *dPriv = ctx->dPriv;
- __DRIdrawable *rPriv = ctx->rPriv;
- boolean flushed = FALSE;
-
- if (dPriv && ctx->d_stamp != dPriv->lastStamp) {
-
- st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
- flushed = TRUE;
- ctx->d_stamp = dPriv->lastStamp;
- st_resize_framebuffer(dri_drawable(dPriv)->stfb, dPriv->w, dPriv->h);
-
- }
-
- if (rPriv && dPriv != rPriv && ctx->r_stamp != rPriv->lastStamp) {
-
- if (!flushed)
- st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
- ctx->r_stamp = rPriv->lastStamp;
- st_resize_framebuffer(dri_drawable(rPriv)->stfb, rPriv->w, rPriv->h);
-
- } else if (rPriv && dPriv == rPriv) {
-
- ctx->r_stamp = ctx->d_stamp;
-
- }
-}
-
-void
-dri1_update_drawables(struct dri_context *ctx,
- struct dri_drawable *draw, struct dri_drawable *read)
-{
- dri_lock(ctx);
- dri1_update_drawables_locked(ctx, draw->dPriv, read->dPriv);
- dri_unlock(ctx);
-
- dri1_propagate_drawable_change(ctx);
-}
-
-static INLINE boolean
-dri1_intersect_src_bbox(struct drm_clip_rect *dst,
- int dst_x,
- int dst_y,
- const struct drm_clip_rect *src,
- const struct drm_clip_rect *bbox)
-{
- int xy1;
- int xy2;
-
- xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 :
- (int)bbox->x1 + dst_x;
- xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 :
- (int)bbox->x2 + dst_x;
- if (xy1 >= xy2 || xy1 < 0)
- return FALSE;
-
- dst->x1 = xy1;
- dst->x2 = xy2;
-
- xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 :
- (int)bbox->y1 + dst_y;
- xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 :
- (int)bbox->y2 + dst_y;
- if (xy1 >= xy2 || xy1 < 0)
- return FALSE;
-
- dst->y1 = xy1;
- dst->y2 = xy2;
- return TRUE;
-}
-
-static void
-dri1_swap_copy(struct dri_context *ctx,
- struct pipe_surface *dst,
- struct pipe_surface *src,
- __DRIdrawable * dPriv, const struct drm_clip_rect *bbox)
-{
- struct pipe_context *pipe = ctx->pipe;
- struct drm_clip_rect clip;
- struct drm_clip_rect *cur;
int i;
- cur = dPriv->pClipRects;
-
- for (i = 0; i < dPriv->numClipRects; ++i) {
- if (dri1_intersect_src_bbox(&clip, dPriv->x, dPriv->y, cur++, bbox)) {
- if (pipe->surface_copy) {
- pipe->surface_copy(pipe, dst, clip.x1, clip.y1,
- src,
- (int)clip.x1 - dPriv->x,
- (int)clip.y1 - dPriv->y,
- clip.x2 - clip.x1, clip.y2 - clip.y1);
- } else {
- util_surface_copy(pipe, FALSE, dst, clip.x1, clip.y1,
- src,
- (int)clip.x1 - dPriv->x,
- (int)clip.y1 - dPriv->y,
- clip.x2 - clip.x1, clip.y2 - clip.y1);
- }
- }
- }
-}
-
-static void
-dri1_copy_to_front(struct dri_context *ctx,
- struct pipe_surface *surf,
- __DRIdrawable * dPriv,
- const struct drm_clip_rect *sub_box,
- struct pipe_fence_handle **fence)
-{
- struct pipe_context *pipe = ctx->pipe;
- boolean save_lost_lock;
- uint cur_w;
- uint cur_h;
- struct drm_clip_rect bbox;
- boolean visible = TRUE;
-
- *fence = NULL;
-
- dri_lock(ctx);
- save_lost_lock = ctx->stLostLock;
- dri1_update_drawables_locked(ctx, dPriv, dPriv);
- st_get_framebuffer_dimensions(dri_drawable(dPriv)->stfb, &cur_w, &cur_h);
-
- bbox.x1 = 0;
- bbox.x2 = cur_w;
- bbox.y1 = 0;
- bbox.y2 = cur_h;
-
- if (sub_box)
- visible = dri1_intersect_src_bbox(&bbox, 0, 0, &bbox, sub_box);
-
- if (visible && __dri1_api_hooks->present_locked) {
-
- __dri1_api_hooks->present_locked(pipe,
- surf,
- dPriv->pClipRects,
- dPriv->numClipRects,
- dPriv->x, dPriv->y, &bbox, fence);
-
- } else if (visible && __dri1_api_hooks->front_srf_locked) {
-
- struct pipe_surface *front = __dri1_api_hooks->front_srf_locked(pipe);
+ dri1_swap_fences_clear(drawable);
- if (front)
- dri1_swap_copy(ctx, front, surf, dPriv, &bbox);
-
- st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, fence);
- }
-
- ctx->stLostLock = save_lost_lock;
-
- /**
- * FIXME: Revisit this: Update drawables on copy_sub_buffer ?
- */
-
- if (!sub_box)
- dri1_update_drawables_locked(ctx, ctx->dPriv, ctx->rPriv);
-
- dri_unlock(ctx);
- dri1_propagate_drawable_change(ctx);
-}
-
-void
-dri1_flush_frontbuffer(struct pipe_screen *screen,
- struct pipe_surface *surf, void *context_private)
-{
- struct dri_context *ctx = (struct dri_context *)context_private;
- struct pipe_fence_handle *dummy_fence;
+ pipe_surface_reference(&drawable->dri1_surface, NULL);
+ for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
+ pipe_texture_reference(&drawable->textures[i], NULL);
- dri1_copy_to_front(ctx, surf, ctx->dPriv, NULL, &dummy_fence);
- screen->fence_reference(screen, &dummy_fence, NULL);
+ dri_destroy_st_framebuffer(drawable->stfb);
- /**
- * FIXME: Do we need swap throttling here?
- */
-}
-
-void
-dri_swap_buffers(__DRIdrawable * dPriv)
-{
- struct dri_context *ctx;
- struct pipe_surface *back_surf;
- struct dri_drawable *draw = dri_drawable(dPriv);
- struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
- struct pipe_fence_handle *fence;
- struct st_context *st = st_get_current();
-
- assert(__dri1_api_hooks != NULL);
-
- if (!st)
- return; /* For now */
-
- ctx = (struct dri_context *)st->pipe->priv;
-
- st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf);
- if (back_surf) {
- st_notify_swapbuffers(draw->stfb);
- st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
- fence = dri_swap_fences_pop_front(draw);
- if (fence) {
- (void)screen->fence_finish(screen, fence, 0);
- screen->fence_reference(screen, &fence, NULL);
- }
- dri1_copy_to_front(ctx, back_surf, dPriv, NULL, &fence);
- dri_swap_fences_push_back(draw, fence);
- screen->fence_reference(screen, &fence, NULL);
- }
-}
-
-void
-dri_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h)
-{
- struct pipe_screen *screen = dri_screen(dPriv->driScreenPriv)->pipe_screen;
- struct drm_clip_rect sub_bbox;
- struct dri_context *ctx;
- struct pipe_surface *back_surf;
- struct dri_drawable *draw = dri_drawable(dPriv);
- struct pipe_fence_handle *dummy_fence;
- struct st_context *st = st_get_current();
-
- assert(__dri1_api_hooks != NULL);
-
- if (!st)
- return;
-
- ctx = (struct dri_context *)st->pipe->priv;
-
- sub_bbox.x1 = x;
- sub_bbox.x2 = x + w;
- sub_bbox.y1 = y;
- sub_bbox.y2 = y + h;
+ drawable->desired_fences = 0;
- st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf);
- if (back_surf) {
- st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
- dri1_copy_to_front(ctx, back_surf, dPriv, &sub_bbox, &dummy_fence);
- screen->fence_reference(screen, &dummy_fence, NULL);
- }
+ FREE(drawable);
}
/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_drawable.h b/src/gallium/state_trackers/dri/dri_drawable.h
index 8bc59cb4c3d..7f687b65f23 100644
--- a/src/gallium/state_trackers/dri/dri_drawable.h
+++ b/src/gallium/state_trackers/dri/dri_drawable.h
@@ -29,6 +29,8 @@
#define DRI_DRAWABLE_H
#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "state_tracker/st_api.h"
struct pipe_surface;
struct pipe_fence_handle;
@@ -44,26 +46,26 @@ struct dri_drawable
__DRIdrawable *dPriv;
__DRIscreen *sPriv;
- unsigned attachments[8];
- unsigned num_attachments;
-
- boolean is_pixmap;
+ /* gallium */
+ struct st_framebuffer_iface *stfb;
+ struct st_visual stvis;
__DRIbuffer old[8];
unsigned old_num;
unsigned old_w;
unsigned old_h;
- /* gallium */
- struct st_framebuffer *stfb;
+ struct pipe_texture *textures[ST_ATTACHMENT_COUNT];
+ unsigned int texture_mask, texture_stamp;
+
struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX];
unsigned int head;
unsigned int tail;
unsigned int desired_fences;
unsigned int cur_fences;
- enum pipe_format color_format;
- enum pipe_format depth_stencil_format;
+ /* used only by DRI1 */
+ struct pipe_surface *dri1_surface;
};
static INLINE struct dri_drawable *
@@ -80,20 +82,6 @@ dri_create_buffer(__DRIscreen * sPriv,
__DRIdrawable * dPriv,
const __GLcontextModes * visual, boolean isPixmap);
-void
-dri_update_buffer(struct pipe_screen *screen, void *context_private);
-
-void
-dri_flush_frontbuffer(struct pipe_screen *screen,
- struct pipe_surface *surf, void *context_private);
-
-void dri_swap_buffers(__DRIdrawable * dPriv);
-
-void
-dri_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h);
-
-void dri_get_buffers(__DRIdrawable * dPriv);
-
void dri_destroy_buffer(__DRIdrawable * dPriv);
void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
@@ -102,13 +90,6 @@ void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target,
__DRIdrawable *dPriv);
-void
-dri1_update_drawables(struct dri_context *ctx,
- struct dri_drawable *draw, struct dri_drawable *read);
-
-void
-dri1_flush_frontbuffer(struct pipe_screen *screen,
- struct pipe_surface *surf, void *context_private);
#endif
/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_extensions.c b/src/gallium/state_trackers/dri/dri_extensions.c
index 800677a2d1e..df458e1eb0f 100644
--- a/src/gallium/state_trackers/dri/dri_extensions.c
+++ b/src/gallium/state_trackers/dri/dri_extensions.c
@@ -38,9 +38,11 @@
void
dri_init_extensions(struct dri_context *ctx)
{
+ struct st_context *st = (struct st_context *) ctx->st;
+
/* New extensions should be added in mesa/state_tracker/st_extensions.c
* and not in this file. */
- driInitExtensions(ctx->st->ctx, NULL, GL_FALSE);
+ driInitExtensions(st->ctx, NULL, GL_FALSE);
}
/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c
index 7ccad8f5dd6..17b9f1c5faf 100644
--- a/src/gallium/state_trackers/dri/dri_screen.c
+++ b/src/gallium/state_trackers/dri/dri_screen.c
@@ -36,11 +36,13 @@
#include "dri_screen.h"
#include "dri_context.h"
#include "dri_drawable.h"
+#include "dri_st_api.h"
+#include "dri1.h"
+#include "util/u_inlines.h"
#include "pipe/p_screen.h"
#include "pipe/p_format.h"
#include "state_tracker/drm_api.h"
-#include "state_tracker/dri1_api.h"
#include "util/u_debug.h"
@@ -53,7 +55,7 @@ PUBLIC const char __driConfigOptions[] =
DRI_CONF_ALLOW_LARGE_TEXTURES(1)
DRI_CONF_SECTION_END DRI_CONF_END;
- const uint __driNConfigOptions = 3;
+const uint __driNConfigOptions = 3;
static const __DRItexBufferExtension dri2TexBufferExtension = {
{ __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
@@ -66,10 +68,23 @@ dri2_flush_drawable(__DRIdrawable *draw)
{
}
+static void
+dri2_invalidate_drawable(__DRIdrawable *dPriv)
+{
+ struct dri_drawable *drawable = dri_drawable(dPriv);
+ struct dri_context *ctx = dri_context(dPriv->driContextPriv);
+
+ dri2InvalidateDrawable(dPriv);
+ drawable->dPriv->lastStamp = *drawable->dPriv->pStamp;
+
+ if (ctx)
+ ctx->st->notify_invalid_framebuffer(ctx->st, drawable->stfb);
+}
+
static const __DRI2flushExtension dri2FlushExtension = {
{ __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
dri2_flush_drawable,
- dri2InvalidateDrawable,
+ dri2_invalidate_drawable,
};
static const __DRIextension *dri_screen_extensions[] = {
@@ -83,9 +98,7 @@ static const __DRI2flushExtension dri2FlushExtension = {
NULL
};
-struct dri1_api *__dri1_api_hooks = NULL;
-
-static const __DRIconfig **
+const __DRIconfig **
dri_fill_in_modes(struct dri_screen *screen,
unsigned pixel_bits)
{
@@ -229,6 +242,68 @@ dri_fill_in_modes(struct dri_screen *screen,
}
/**
+ * Roughly the converse of dri_fill_in_modes.
+ */
+void
+dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
+ const __GLcontextModes *mode)
+{
+ memset(stvis, 0, sizeof(*stvis));
+
+ stvis->samples = mode->samples;
+ stvis->render_buffer = ST_ATTACHMENT_INVALID;
+
+ if (mode->redBits == 8) {
+ if (mode->alphaBits == 8)
+ stvis->color_format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ else
+ stvis->color_format = PIPE_FORMAT_B8G8R8X8_UNORM;
+ } else {
+ stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM;
+ }
+
+ switch (mode->depthBits) {
+ default:
+ case 0:
+ stvis->depth_stencil_format = PIPE_FORMAT_NONE;
+ break;
+ case 16:
+ stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
+ break;
+ case 24:
+ if (mode->stencilBits == 0) {
+ stvis->depth_stencil_format = (screen->d_depth_bits_last) ?
+ PIPE_FORMAT_Z24X8_UNORM:
+ PIPE_FORMAT_X8Z24_UNORM;
+ } else {
+ stvis->depth_stencil_format = (screen->sd_depth_bits_last) ?
+ PIPE_FORMAT_Z24S8_UNORM:
+ PIPE_FORMAT_S8Z24_UNORM;
+ }
+ break;
+ case 32:
+ stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM;
+ break;
+ }
+
+ stvis->accum_format = (mode->haveAccumBuffer) ?
+ PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
+
+ stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
+ if (mode->doubleBufferMode)
+ stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
+ if (mode->stereoMode) {
+ stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
+ if (mode->doubleBufferMode)
+ stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
+ }
+
+ if (mode->haveDepthBuffer || mode->haveStencilBuffer)
+ stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK;
+ /* let the state tracker allocate the accum buffer */
+}
+
+/**
* Get information about previous buffer swaps.
*/
static int
@@ -240,73 +315,31 @@ dri_get_swap_info(__DRIdrawable * dPriv, __DRIswapInfo * sInfo)
return 0;
}
-static INLINE void
-dri_copy_version(struct dri1_api_version *dst,
- const struct __DRIversionRec *src)
-{
- dst->major = src->major;
- dst->minor = src->minor;
- dst->patch_level = src->patch;
-}
-
-static const __DRIconfig **
-dri_init_screen(__DRIscreen * sPriv)
+static void
+dri_destroy_screen(__DRIscreen * sPriv)
{
- struct dri_screen *screen;
- const __DRIconfig **configs;
- struct dri1_create_screen_arg arg;
+ struct dri_screen *screen = dri_screen(sPriv);
+ int i;
- screen = CALLOC_STRUCT(dri_screen);
- if (!screen)
- return NULL;
+ if (screen->dri1_pipe)
+ screen->dri1_pipe->destroy(screen->dri1_pipe);
- screen->api = drm_api_create();
- screen->sPriv = sPriv;
- screen->fd = sPriv->fd;
- screen->drmLock = (drmLock *) & sPriv->pSAREA->lock;
+ if (screen->smapi)
+ dri_destroy_st_manager(screen->smapi);
+ if (screen->pipe_screen)
+ screen->pipe_screen->destroy(screen->pipe_screen);
- sPriv->private = (void *)screen;
- sPriv->extensions = dri_screen_extensions;
-
- arg.base.mode = DRM_CREATE_DRI1;
- arg.lf = &dri1_lf;
- arg.ddx_info = sPriv->pDevPriv;
- arg.ddx_info_size = sPriv->devPrivSize;
- arg.sarea = sPriv->pSAREA;
- dri_copy_version(&arg.ddx_version, &sPriv->ddx_version);
- dri_copy_version(&arg.dri_version, &sPriv->dri_version);
- dri_copy_version(&arg.drm_version, &sPriv->drm_version);
- arg.api = NULL;
-
- screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg.base);
-
- if (!screen->pipe_screen || !arg.api) {
- debug_printf("%s: failed to create dri1 screen\n", __FUNCTION__);
- goto out_no_screen;
+ for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) {
+ FREE(screen->optionCache.info[i].name);
+ FREE(screen->optionCache.info[i].ranges);
}
- __dri1_api_hooks = arg.api;
-
- screen->pipe_screen->flush_frontbuffer = dri1_flush_frontbuffer;
- driParseOptionInfo(&screen->optionCache,
- __driConfigOptions, __driNConfigOptions);
-
- /**
- * FIXME: If the driver supports format conversion swapbuffer blits, we might
- * want to support other color bit depths than the server is currently
- * using.
- */
-
- configs = dri_fill_in_modes(screen, sPriv->fbBPP);
- if (!configs)
- goto out_no_configs;
+ FREE(screen->optionCache.info);
+ FREE(screen->optionCache.values);
- return configs;
- out_no_configs:
- screen->pipe_screen->destroy(screen->pipe_screen);
- out_no_screen:
FREE(screen);
- return NULL;
+ sPriv->private = NULL;
+ sPriv->extensions = NULL;
}
/**
@@ -324,7 +357,7 @@ dri_init_screen2(__DRIscreen * sPriv)
screen = CALLOC_STRUCT(dri_screen);
if (!screen)
- goto fail;
+ return NULL;
screen->api = drm_api_create();
screen->sPriv = sPriv;
@@ -339,9 +372,9 @@ dri_init_screen2(__DRIscreen * sPriv)
goto fail;
}
- /* We need to hook in here */
- screen->pipe_screen->update_buffer = dri_update_buffer;
- screen->pipe_screen->flush_frontbuffer = dri_flush_frontbuffer;
+ screen->smapi = dri_create_st_manager(screen);
+ if (!screen->smapi)
+ goto fail;
driParseOptionInfo(&screen->optionCache,
__driConfigOptions, __driNConfigOptions);
@@ -350,46 +383,27 @@ dri_init_screen2(__DRIscreen * sPriv)
dri2_ext->getBuffersWithFormat != NULL;
return dri_fill_in_modes(screen, 32);
- fail:
+fail:
+ dri_destroy_screen(sPriv);
return NULL;
}
-static void
-dri_destroy_screen(__DRIscreen * sPriv)
-{
- struct dri_screen *screen = dri_screen(sPriv);
- int i;
-
- screen->pipe_screen->destroy(screen->pipe_screen);
-
- for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) {
- FREE(screen->optionCache.info[i].name);
- FREE(screen->optionCache.info[i].ranges);
- }
-
- FREE(screen->optionCache.info);
- FREE(screen->optionCache.values);
-
- FREE(screen);
- sPriv->private = NULL;
-}
-
-PUBLIC const struct __DriverAPIRec driDriverAPI = {
- .InitScreen = dri_init_screen,
+const struct __DriverAPIRec driDriverAPI = {
.DestroyScreen = dri_destroy_screen,
.CreateContext = dri_create_context,
.DestroyContext = dri_destroy_context,
.CreateBuffer = dri_create_buffer,
.DestroyBuffer = dri_destroy_buffer,
- .SwapBuffers = dri_swap_buffers,
.MakeCurrent = dri_make_current,
.UnbindContext = dri_unbind_context,
.GetSwapInfo = dri_get_swap_info,
.GetDrawableMSC = driDrawableGetMSC32,
.WaitForMSC = driWaitForMSC32,
- .CopySubBuffer = dri_copy_sub_buffer,
- .InitScreen = dri_init_screen,
.InitScreen2 = dri_init_screen2,
+
+ .InitScreen = dri1_init_screen,
+ .SwapBuffers = dri1_swap_buffers,
+ .CopySubBuffer = dri1_copy_sub_buffer,
};
/* This is the table of extensions that the loader will dlsym() for. */
diff --git a/src/gallium/state_trackers/dri/dri_screen.h b/src/gallium/state_trackers/dri/dri_screen.h
index 75a0ee4250e..e9944e0f63e 100644
--- a/src/gallium/state_trackers/dri/dri_screen.h
+++ b/src/gallium/state_trackers/dri/dri_screen.h
@@ -36,8 +36,9 @@
#include "xmlconfig.h"
#include "pipe/p_compiler.h"
-
-#include "state_tracker/dri1_api.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "state_tracker/st_api.h"
struct dri_screen
{
@@ -60,6 +61,11 @@ struct dri_screen
boolean d_depth_bits_last;
boolean sd_depth_bits_last;
boolean auto_fake_front;
+
+ struct st_manager *smapi;
+
+ /* used only by DRI1 */
+ struct pipe_context *dri1_pipe;
};
/** cast wrapper */
@@ -69,11 +75,14 @@ dri_screen(__DRIscreen * sPriv)
return (struct dri_screen *)sPriv->private;
}
-/***********************************************************************
- * dri_screen.c
- */
+extern const uint __driNConfigOptions;
+
+const __DRIconfig **
+dri_fill_in_modes(struct dri_screen *screen, unsigned pixel_bits);
-extern struct dri1_api *__dri1_api_hooks;
+void
+dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
+ const __GLcontextModes *mode);
#endif
diff --git a/src/gallium/state_trackers/dri/dri_st_api.c b/src/gallium/state_trackers/dri/dri_st_api.c
new file mode 100644
index 00000000000..2cde01967d8
--- /dev/null
+++ b/src/gallium/state_trackers/dri/dri_st_api.c
@@ -0,0 +1,445 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * 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.
+ *
+ * Authors:
+ * Chia-I Wu <[email protected]>
+ */
+
+#include "util/u_memory.h"
+#include "util/u_inlines.h"
+#include "util/u_format.h"
+#include "util/u_debug.h"
+#include "state_tracker/drm_api.h"
+#include "state_tracker/st_manager.h" /* for st_manager_create_api */
+
+#include "dri_screen.h"
+#include "dri_context.h"
+#include "dri_drawable.h"
+#include "dri_st_api.h"
+#include "dri1.h"
+
+static struct {
+ int32_t refcnt;
+ struct st_api *stapi;
+} dri_st_api;
+
+/**
+ * Get the format of an attachment.
+ */
+static INLINE enum pipe_format
+dri_drawable_get_format(struct dri_drawable *drawable,
+ enum st_attachment_type statt)
+{
+ enum pipe_format format;
+
+ switch (statt) {
+ case ST_ATTACHMENT_FRONT_LEFT:
+ case ST_ATTACHMENT_BACK_LEFT:
+ case ST_ATTACHMENT_FRONT_RIGHT:
+ case ST_ATTACHMENT_BACK_RIGHT:
+ format = drawable->stvis.color_format;
+ break;
+ case ST_ATTACHMENT_DEPTH_STENCIL:
+ format = drawable->stvis.depth_stencil_format;
+ break;
+ default:
+ format = PIPE_FORMAT_NONE;
+ break;
+ }
+
+ return format;
+}
+
+/**
+ * Process __DRIbuffer and convert them into pipe_textures.
+ */
+static void
+dri_drawable_process_buffers(struct dri_drawable *drawable,
+ __DRIbuffer *buffers, unsigned count)
+{
+ struct dri_screen *screen = dri_screen(drawable->sPriv);
+ __DRIdrawable *dri_drawable = drawable->dPriv;
+ struct pipe_texture templ;
+ struct winsys_handle whandle;
+ boolean have_depth = FALSE;
+ unsigned i;
+
+ if (drawable->old_num == count &&
+ drawable->old_w == dri_drawable->w &&
+ drawable->old_h == dri_drawable->h &&
+ memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0)
+ return;
+
+ for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
+ pipe_texture_reference(&drawable->textures[i], NULL);
+
+ memset(&templ, 0, sizeof(templ));
+ templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ templ.target = PIPE_TEXTURE_2D;
+ templ.last_level = 0;
+ templ.width0 = dri_drawable->w;
+ templ.height0 = dri_drawable->h;
+ templ.depth0 = 1;
+
+ memset(&whandle, 0, sizeof(whandle));
+
+ for (i = 0; i < count; i++) {
+ __DRIbuffer *buf = &buffers[i];
+ enum st_attachment_type statt;
+ enum pipe_format format;
+
+ switch (buf->attachment) {
+ case __DRI_BUFFER_FRONT_LEFT:
+ if (!screen->auto_fake_front) {
+ statt = ST_ATTACHMENT_INVALID;
+ break;
+ }
+ /* fallthrough */
+ case __DRI_BUFFER_FAKE_FRONT_LEFT:
+ statt = ST_ATTACHMENT_FRONT_LEFT;
+ break;
+ case __DRI_BUFFER_BACK_LEFT:
+ statt = ST_ATTACHMENT_BACK_LEFT;
+ break;
+ case __DRI_BUFFER_DEPTH:
+ case __DRI_BUFFER_DEPTH_STENCIL:
+ case __DRI_BUFFER_STENCIL:
+ statt = ST_ATTACHMENT_DEPTH_STENCIL;
+ /* use only the first depth/stencil buffer */
+ if (have_depth)
+ statt = ST_ATTACHMENT_INVALID;
+ else
+ have_depth = TRUE;
+ break;
+ default:
+ statt = ST_ATTACHMENT_INVALID;
+ break;
+ }
+
+ format = dri_drawable_get_format(drawable, statt);
+ if (statt == ST_ATTACHMENT_INVALID || format == PIPE_FORMAT_NONE)
+ continue;
+
+ templ.format = format;
+ whandle.handle = buf->name;
+ whandle.stride = buf->pitch;
+
+ drawable->textures[statt] =
+ screen->pipe_screen->texture_from_handle(screen->pipe_screen,
+ &templ, &whandle);
+ }
+
+ drawable->old_num = count;
+ drawable->old_w = dri_drawable->w;
+ drawable->old_h = dri_drawable->h;
+ memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count);
+}
+
+/**
+ * Retrieve __DRIbuffer from the DRI loader.
+ */
+static __DRIbuffer *
+dri_drawable_get_buffers(struct dri_drawable *drawable,
+ const enum st_attachment_type *statts,
+ unsigned *count)
+{
+ __DRIdrawable *dri_drawable = drawable->dPriv;
+ struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
+ boolean with_format;
+ __DRIbuffer *buffers;
+ int num_buffers;
+ unsigned attachments[8];
+ unsigned num_attachments, i;
+
+ assert(loader);
+ with_format = (loader->base.version > 2 && loader->getBuffersWithFormat);
+
+ num_attachments = 0;
+ for (i = 0; i < *count; i++) {
+ enum pipe_format format;
+ int att;
+
+ format = dri_drawable_get_format(drawable, statts[i]);
+ if (format == PIPE_FORMAT_NONE)
+ continue;
+
+ switch (statts[i]) {
+ case ST_ATTACHMENT_FRONT_LEFT:
+ att = __DRI_BUFFER_FRONT_LEFT;
+ break;
+ case ST_ATTACHMENT_BACK_LEFT:
+ att = __DRI_BUFFER_BACK_LEFT;
+ break;
+ case ST_ATTACHMENT_FRONT_RIGHT:
+ att = __DRI_BUFFER_FRONT_RIGHT;
+ break;
+ case ST_ATTACHMENT_BACK_RIGHT:
+ att = __DRI_BUFFER_BACK_RIGHT;
+ break;
+ case ST_ATTACHMENT_DEPTH_STENCIL:
+ att = __DRI_BUFFER_DEPTH_STENCIL;
+ break;
+ default:
+ att = -1;
+ break;
+ }
+
+ if (att >= 0) {
+ attachments[num_attachments++] = att;
+ if (with_format) {
+ attachments[num_attachments++] =
+ util_format_get_blocksizebits(format);
+ }
+ }
+ }
+
+ if (with_format) {
+ num_attachments /= 2;
+ buffers = loader->getBuffersWithFormat(dri_drawable,
+ &dri_drawable->w, &dri_drawable->h,
+ attachments, num_attachments,
+ &num_buffers, dri_drawable->loaderPrivate);
+ }
+ else {
+ buffers = loader->getBuffers(dri_drawable,
+ &dri_drawable->w, &dri_drawable->h,
+ attachments, num_attachments,
+ &num_buffers, dri_drawable->loaderPrivate);
+ }
+
+ if (buffers) {
+ /* set one cliprect to cover the whole dri_drawable */
+ dri_drawable->x = 0;
+ dri_drawable->y = 0;
+ dri_drawable->backX = 0;
+ dri_drawable->backY = 0;
+ dri_drawable->numClipRects = 1;
+ dri_drawable->pClipRects[0].x1 = 0;
+ dri_drawable->pClipRects[0].y1 = 0;
+ dri_drawable->pClipRects[0].x2 = dri_drawable->w;
+ dri_drawable->pClipRects[0].y2 = dri_drawable->h;
+ dri_drawable->numBackClipRects = 1;
+ dri_drawable->pBackClipRects[0].x1 = 0;
+ dri_drawable->pBackClipRects[0].y1 = 0;
+ dri_drawable->pBackClipRects[0].x2 = dri_drawable->w;
+ dri_drawable->pBackClipRects[0].y2 = dri_drawable->h;
+
+ *count = num_buffers;
+ }
+
+ return buffers;
+}
+
+static boolean
+dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
+ const enum st_attachment_type *statts,
+ unsigned count,
+ struct pipe_texture **out)
+{
+ struct dri_drawable *drawable =
+ (struct dri_drawable *) stfbi->st_manager_private;
+ unsigned statt_mask, i;
+
+ statt_mask = 0x0;
+ for (i = 0; i < count; i++)
+ statt_mask |= (1 << statts[i]);
+
+ /*
+ * dPriv->pStamp is the server stamp. It should be accessed with a lock, at
+ * least for DRI1. dPriv->lastStamp is the client stamp. It has the value
+ * of the server stamp when last checked.
+ *
+ * This function updates the textures and records the stamp of the textures.
+ */
+ if (drawable->texture_stamp != drawable->dPriv->lastStamp ||
+ (statt_mask & ~drawable->texture_mask)) {
+ if (__dri1_api_hooks) {
+ dri1_allocate_textures(drawable,
+ drawable->dPriv->w, drawable->dPriv->h, statt_mask);
+ }
+ else {
+ __DRIbuffer *buffers;
+ unsigned num_buffers = count;
+
+ buffers = dri_drawable_get_buffers(drawable, statts, &num_buffers);
+ dri_drawable_process_buffers(drawable, buffers, num_buffers);
+ }
+
+ drawable->texture_stamp = drawable->dPriv->lastStamp;
+ drawable->texture_mask = statt_mask;
+ }
+
+ if (!out)
+ return TRUE;
+
+ for (i = 0; i < count; i++) {
+ out[i] = NULL;
+ pipe_texture_reference(&out[i], drawable->textures[statts[i]]);
+ }
+
+ return TRUE;
+}
+
+static boolean
+dri_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
+ enum st_attachment_type statt)
+{
+ struct dri_drawable *drawable =
+ (struct dri_drawable *) stfbi->st_manager_private;
+ struct __DRIdri2LoaderExtensionRec *loader =
+ drawable->sPriv->dri2.loader;
+
+ if (__dri1_api_hooks) {
+ struct pipe_texture *ptex = drawable->textures[statt];
+ if (ptex)
+ dri1_flush_frontbuffer(drawable, ptex);
+ return TRUE;
+ }
+
+ if (statt == ST_ATTACHMENT_FRONT_LEFT && loader->flushFrontBuffer) {
+ loader->flushFrontBuffer(drawable->dPriv,
+ drawable->dPriv->loaderPrivate);
+ }
+
+ return TRUE;
+}
+
+/**
+ * Create a framebuffer from the given drawable.
+ */
+struct st_framebuffer_iface *
+dri_create_st_framebuffer(struct dri_drawable *drawable)
+{
+ struct st_framebuffer_iface *stfbi;
+
+ stfbi = CALLOC_STRUCT(st_framebuffer_iface);
+ if (stfbi) {
+ stfbi->visual = &drawable->stvis;
+ stfbi->flush_front = dri_st_framebuffer_flush_front;
+ stfbi->validate = dri_st_framebuffer_validate;
+ stfbi->st_manager_private = (void *) drawable;
+ }
+
+ return stfbi;
+}
+
+/**
+ * Destroy a framebuffer.
+ */
+void
+dri_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
+{
+ FREE(stfbi);
+}
+
+/**
+ * Return the texture at an attachment. Allocate the texture if it does not
+ * exist.
+ */
+struct pipe_texture *
+dri_get_st_framebuffer_texture(struct st_framebuffer_iface *stfbi,
+ enum st_attachment_type statt)
+{
+ struct dri_drawable *drawable =
+ (struct dri_drawable *) stfbi->st_manager_private;
+
+ if (!(drawable->texture_mask & (1 << statt))) {
+ enum st_attachment_type statts[ST_ATTACHMENT_COUNT];
+ unsigned i, count = 0;
+
+ /* make sure DRI2 does not destroy existing buffers */
+ for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
+ if (drawable->texture_mask & (1 << i)) {
+ statts[count++] = i;
+ }
+ }
+ statts[count++] = statt;
+
+ drawable->texture_stamp = drawable->dPriv->lastStamp - 1;
+ dri_st_framebuffer_validate(stfbi, statts, count, NULL);
+ }
+
+ return drawable->textures[statt];
+}
+
+/**
+ * Add a reference to the st_api of the state tracker.
+ */
+static void
+_dri_get_st_api(void)
+{
+ p_atomic_inc(&dri_st_api.refcnt);
+ if (p_atomic_read(&dri_st_api.refcnt) == 1)
+ dri_st_api.stapi = st_manager_create_api();
+}
+
+/**
+ * Remove a reference to the st_api of the state tracker.
+ */
+static void
+_dri_put_st_api(void)
+{
+ struct st_api *stapi = dri_st_api.stapi;
+
+ if (p_atomic_dec_zero(&dri_st_api.refcnt)) {
+ stapi->destroy(dri_st_api.stapi);
+ dri_st_api.stapi = NULL;
+ }
+}
+
+/**
+ * Create a state tracker manager from the given screen.
+ */
+struct st_manager *
+dri_create_st_manager(struct dri_screen *screen)
+{
+ struct st_manager *smapi;
+
+ smapi = CALLOC_STRUCT(st_manager);
+ if (smapi) {
+ smapi->screen = screen->pipe_screen;
+ _dri_get_st_api();
+ }
+
+ return smapi;
+}
+
+/**
+ * Destroy a state tracker manager.
+ */
+void
+dri_destroy_st_manager(struct st_manager *smapi)
+{
+ _dri_put_st_api();
+ FREE(smapi);
+}
+
+/**
+ * Return the st_api of OpenGL state tracker.
+ */
+struct st_api *
+dri_get_st_api(void)
+{
+ assert(dri_st_api.stapi);
+ return dri_st_api.stapi;
+}
diff --git a/src/gallium/state_trackers/dri/dri_st_api.h b/src/gallium/state_trackers/dri/dri_st_api.h
new file mode 100644
index 00000000000..7cf522e4690
--- /dev/null
+++ b/src/gallium/state_trackers/dri/dri_st_api.h
@@ -0,0 +1,55 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * 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.
+ *
+ * Authors:
+ * Chia-I Wu <[email protected]>
+ */
+
+#ifndef _DRI_ST_API_H_
+#define _DRI_ST_API_H_
+
+#include "state_tracker/st_api.h"
+
+struct dri_screen;
+struct dri_drawable;
+
+struct st_api *
+dri_get_st_api(void);
+
+struct st_manager *
+dri_create_st_manager(struct dri_screen *screen);
+
+void
+dri_destroy_st_manager(struct st_manager *smapi);
+
+struct st_framebuffer_iface *
+dri_create_st_framebuffer(struct dri_drawable *drawable);
+
+void
+dri_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi);
+
+struct pipe_texture *
+dri_get_st_framebuffer_texture(struct st_framebuffer_iface *stfbi,
+ enum st_attachment_type statt);
+
+#endif /* _DRI_ST_API_H_ */