This is only compile tested with crossmingw.
V2:
- reference count stw_framebuffer
'stw_framebuffer.c',
'stw_getprocaddress.c',
'stw_pixelformat.c',
+ 'stw_st.c',
'stw_tls.c',
'stw_wgl.c',
]
#include <windows.h>
-#include "main/mtypes.h"
-#include "main/context.h"
#include "pipe/p_compiler.h"
#include "pipe/p_context.h"
+#include "state_tracker/st_api.h"
+
+/* for _mesa_share_state */
#include "state_tracker/st_context.h"
-#include "state_tracker/st_public.h"
+#include "main/context.h"
#include "stw_icd.h"
#include "stw_device.h"
#include "stw_tls.h"
-static INLINE struct stw_context *
-stw_context(GLcontext *glctx)
-{
- if(!glctx)
- return NULL;
- assert(glctx->DriverCtx);
- return (struct stw_context *)glctx->DriverCtx;
-}
-
static INLINE struct stw_context *
stw_current_context(void)
{
- /* We must check if multiple threads are being used or GET_CURRENT_CONTEXT
- * might return the current context of the thread first seen. */
- _glapi_check_multithread();
+ struct st_context_iface *st;
- {
- GET_CURRENT_CONTEXT( glctx );
- return stw_context(glctx);
- }
+ st = (stw_dev) ? stw_dev->stapi->get_current(stw_dev->stapi) : NULL;
+
+ return (struct stw_context *) ((st) ? st->st_manager_private : NULL);
}
BOOL APIENTRY
ctx2 = stw_lookup_context_locked( dhglrc2 );
if (ctx1 && ctx2) {
- ret = _mesa_share_state(ctx2->st->ctx, ctx1->st->ctx);
+ struct st_context *st1, *st2;
+
+ st1 = (struct st_context *) ctx1->st;
+ st2 = (struct st_context *) ctx2->st;
+ ret = _mesa_share_state(st2->ctx, st1->ctx);
}
pipe_mutex_unlock( stw_dev->ctx_mutex );
return ret;
}
-static void
-stw_viewport(GLcontext * glctx, GLint x, GLint y,
- GLsizei width, GLsizei height)
-{
- struct stw_context *ctx = (struct stw_context *)glctx->DriverCtx;
- struct stw_framebuffer *fb;
-
- fb = stw_framebuffer_from_hdc( ctx->hdc );
- if(fb) {
- stw_framebuffer_update(fb);
- stw_framebuffer_release(fb);
- }
-}
-
DHGLRC APIENTRY
DrvCreateContext(
HDC hdc )
{
int iPixelFormat;
const struct stw_pixelformat_info *pfi;
- GLvisual visual;
struct stw_context *ctx = NULL;
- struct pipe_context *pipe = NULL;
if(!stw_dev)
return 0;
return 0;
pfi = stw_pixelformat_get_info( iPixelFormat - 1 );
- stw_pixelformat_visual(&visual, pfi);
ctx = CALLOC_STRUCT( stw_context );
if (ctx == NULL)
ctx->hdc = hdc;
ctx->iPixelFormat = iPixelFormat;
- /* priv == hdc, pass to stw_flush_frontbuffer as context_private
- */
- pipe = stw_dev->screen->context_create( stw_dev->screen, hdc );
- if (pipe == NULL)
- goto no_pipe;
-
- ctx->st = st_create_context( pipe, &visual, NULL );
+ ctx->st = stw_dev->stapi->create_context(stw_dev->stapi,
+ stw_dev->smapi, &pfi->stvis, NULL);
if (ctx->st == NULL)
goto no_st_ctx;
- ctx->st->ctx->DriverCtx = ctx;
- ctx->st->ctx->Driver.Viewport = stw_viewport;
+ ctx->st->st_manager_private = (void *) ctx;
pipe_mutex_lock( stw_dev->ctx_mutex );
ctx->dhglrc = handle_table_add(stw_dev->ctx_table, ctx);
return ctx->dhglrc;
no_hglrc:
- st_destroy_context(ctx->st);
- goto no_pipe; /* st_context_destroy already destroys pipe */
+ ctx->st->destroy(ctx->st);
no_st_ctx:
- pipe->destroy( pipe );
-no_pipe:
FREE(ctx);
no_ctx:
return 0;
/* Unbind current if deleting current context. */
if (curctx == ctx)
- st_make_current( NULL, NULL, NULL, NULL );
+ stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
- st_destroy_context(ctx->st);
+ ctx->st->destroy(ctx->st);
FREE(ctx);
ret = TRUE;
curctx = stw_current_context();
if (curctx != NULL) {
if (curctx->dhglrc != dhglrc)
- st_flush(curctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ curctx->st->flush(curctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
/* Return if already current. */
if (curctx->dhglrc == dhglrc && curctx->hdc == hdc) {
fb = stw_framebuffer_from_hdc( hdc );
goto success;
}
+
+ stw_framebuffer_reference(&curctx->current_framebuffer, NULL);
}
if (hdc == NULL || dhglrc == 0) {
- return st_make_current( NULL, NULL, NULL, NULL );
+ return stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
}
pipe_mutex_lock( stw_dev->ctx_mutex );
goto fail;
fb = stw_framebuffer_from_hdc( hdc );
- if(!fb) {
+ if (fb) {
+ stw_framebuffer_update(fb);
+ }
+ else {
/* Applications should call SetPixelFormat before creating a context,
* but not all do, and the opengl32 runtime seems to use a default pixel
* format in some cases, so we must create a framebuffer for those here
if(fb->iPixelFormat != ctx->iPixelFormat)
goto fail;
- /* Lazy allocation of the frame buffer */
- if(!stw_framebuffer_allocate(fb))
- goto fail;
-
/* Bind the new framebuffer */
ctx->hdc = hdc;
- /* pass to stw_flush_frontbuffer as context_private */
- ctx->st->pipe->priv = hdc;
-
- if(!st_make_current( ctx->st, fb->stfb, fb->stfb, hdc ))
+ if (!stw_dev->stapi->make_current(stw_dev->stapi, ctx->st, fb->stfb, fb->stfb))
goto fail;
+ stw_framebuffer_reference(&curctx->current_framebuffer, fb);
+
success:
assert(fb);
if(fb) {
- stw_framebuffer_update(fb);
stw_framebuffer_release(fb);
}
fail:
if(fb)
stw_framebuffer_release(fb);
- st_make_current( NULL, NULL, NULL, NULL );
+ stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
return FALSE;
}
+/**
+ * Flush the current context if it is bound to the framebuffer.
+ */
+void
+stw_flush_current_locked( struct stw_framebuffer *fb )
+{
+ struct stw_context *ctx = stw_current_context();
+
+ if (ctx && ctx->current_framebuffer == fb) {
+ ctx->st->flush(ctx->st,
+ PIPE_FLUSH_RENDER_CACHE |
+ PIPE_FLUSH_SWAPBUFFERS |
+ PIPE_FLUSH_FRAME,
+ NULL);
+ }
+}
+
+/**
+ * Notify the current context that the framebuffer has become invalid.
+ */
+void
+stw_notify_current_locked( struct stw_framebuffer *fb )
+{
+ struct stw_context *ctx = stw_current_context();
+
+ if (ctx && ctx->current_framebuffer == fb)
+ ctx->st->notify_invalid_framebuffer(ctx->st, fb->stfb);
+}
+
/**
* Although WGL allows different dispatch entrypoints per context
*/
#include <windows.h>
-struct st_context;
+struct stw_framebuffer;
+struct st_context_iface;
struct stw_context
{
- struct st_context *st;
+ struct st_context_iface *st;
DHGLRC dhglrc;
int iPixelFormat;
HDC hdc;
+
+ struct stw_framebuffer *current_framebuffer;
};
DHGLRC stw_get_current_context( void );
BOOL stw_make_current( HDC hdc, DHGLRC dhglrc );
+void stw_flush_current_locked( struct stw_framebuffer *fb );
+void stw_notify_current_locked( struct stw_framebuffer *fb );
+
#endif /* STW_CONTEXT_H */
#include "glapi/glthread.h"
#include "util/u_debug.h"
#include "util/u_math.h"
+#include "util/u_memory.h"
#include "pipe/p_screen.h"
-#include "state_tracker/st_public.h"
#include "stw_device.h"
#include "stw_winsys.h"
#include "stw_icd.h"
#include "stw_tls.h"
#include "stw_framebuffer.h"
+#include "stw_st.h"
#ifdef WIN32_THREADS
extern _glthread_Mutex OneTimeLock;
struct stw_device *stw_dev = NULL;
-/**
- * XXX: Dispatch pipe_screen::flush_front_buffer to our
- * stw_winsys::flush_front_buffer.
- */
-static void
-stw_flush_frontbuffer(struct pipe_screen *screen,
- struct pipe_surface *surface,
- void *context_private )
-{
- HDC hdc = (HDC)context_private;
- struct stw_framebuffer *fb;
-
- fb = stw_framebuffer_from_hdc( hdc );
- if (!fb) {
- /* fb can be NULL if window was destroyed already */
- return;
- }
-
- stw_framebuffer_present_locked(hdc, fb, surface);
-}
-
-
boolean
stw_init(const struct stw_winsys *stw_winsys)
{
_glthread_INIT_MUTEX(OneTimeLock);
#endif
+ stw_dev->stapi = stw_st_create_api();
+ stw_dev->smapi = CALLOC_STRUCT(st_manager);
+ if (!stw_dev->stapi || !stw_dev->smapi)
+ goto error1;
+
screen = stw_winsys->create_screen();
if(!screen)
goto error1;
if(stw_winsys->get_adapter_luid)
stw_winsys->get_adapter_luid(screen, &stw_dev->AdapterLuid);
+ stw_dev->smapi->screen = screen;
stw_dev->screen = screen;
- /* XXX
- */
- stw_dev->screen->flush_frontbuffer = &stw_flush_frontbuffer;
-
pipe_mutex_init( stw_dev->ctx_mutex );
pipe_mutex_init( stw_dev->fb_mutex );
return TRUE;
error1:
+ if (stw_dev->smapi)
+ FREE(stw_dev->smapi);
+ if (stw_dev->stapi)
+ stw_dev->stapi->destroy(stw_dev->stapi);
+
stw_dev = NULL;
return FALSE;
}
pipe_mutex_destroy( stw_dev->fb_mutex );
pipe_mutex_destroy( stw_dev->ctx_mutex );
+ FREE(stw_dev->smapi);
+ stw_dev->stapi->destroy(stw_dev->stapi);
+
stw_dev->screen->destroy(stw_dev->screen);
#ifdef WIN32_THREADS
struct pipe_screen;
+struct st_api;
+struct st_manager;
struct stw_framebuffer;
struct stw_device
struct pipe_screen *screen;
+ struct st_api *stapi;
+ struct st_manager *smapi;
+
LUID AdapterLuid;
struct stw_pixelformat_info pixelformats[STW_MAX_PIXELFORMATS];
break;
case WGL_SAMPLE_BUFFERS_ARB:
- *pvalue = pfi->numSampleBuffers;
+ *pvalue = 1;
break;
case WGL_SAMPLES_ARB:
- *pvalue = pfi->numSamples;
+ *pvalue = pfi->stvis.samples;
break;
default:
#include <windows.h>
-#include "main/context.h"
#include "pipe/p_format.h"
#include "pipe/p_screen.h"
#include "util/u_format.h"
-#include "state_tracker/st_context.h"
-#include "state_tracker/st_public.h"
+#include "util/u_memory.h"
+#include "state_tracker/st_api.h"
#include "stw_icd.h"
#include "stw_framebuffer.h"
#include "stw_device.h"
#include "stw_winsys.h"
#include "stw_tls.h"
+#include "stw_context.h"
+#include "stw_st.h"
/**
/**
* Destroy this framebuffer. Both stw_dev::fb_mutex and stw_framebuffer::mutex
- * must be held, by this order. Obviously no further access to fb can be done
- * after this.
+ * must be held, by this order. If there are still references to the
+ * framebuffer, nothing will happen.
*/
static INLINE void
stw_framebuffer_destroy_locked(
{
struct stw_framebuffer **link;
+ /* check the reference count */
+ fb->refcnt--;
+ if (fb->refcnt) {
+ pipe_mutex_unlock( fb->mutex );
+ return;
+ }
+
link = &stw_dev->fb_head;
while (*link != fb)
link = &(*link)->next;
if(fb->shared_surface)
stw_dev->stw_winsys->shared_surface_close(stw_dev->screen, fb->shared_surface);
- st_unreference_framebuffer(fb->stfb);
+ stw_st_destroy_framebuffer_locked(fb->stfb);
pipe_mutex_unlock( fb->mutex );
fb->iPixelFormat = iPixelFormat;
fb->pfi = pfi = stw_pixelformat_get_info( iPixelFormat - 1 );
+ fb->stfb = stw_st_create_framebuffer( fb );
+ if (!fb->stfb) {
+ FREE( fb );
+ return NULL;
+ }
+
+ fb->refcnt = 1;
- stw_pixelformat_visual(&fb->visual, pfi);
-
stw_framebuffer_get_size(fb);
pipe_mutex_init( fb->mutex );
return fb;
}
-
-BOOL
-stw_framebuffer_allocate(
+/**
+ * Have ptr reference fb. The referenced framebuffer should be locked.
+ */
+void
+stw_framebuffer_reference(
+ struct stw_framebuffer **ptr,
struct stw_framebuffer *fb)
{
- assert(fb);
-
- if(!fb->stfb) {
- const struct stw_pixelformat_info *pfi = fb->pfi;
- enum pipe_format colorFormat, depthFormat, stencilFormat;
+ struct stw_framebuffer *old_fb = *ptr;
- colorFormat = pfi->color_format;
+ if (old_fb == fb)
+ return;
- if(util_format_get_component_bits(pfi->depth_stencil_format, UTIL_FORMAT_COLORSPACE_ZS, 0))
- depthFormat = pfi->depth_stencil_format;
- else
- depthFormat = PIPE_FORMAT_NONE;
-
- if(util_format_get_component_bits(pfi->depth_stencil_format, UTIL_FORMAT_COLORSPACE_ZS, 1))
- stencilFormat = pfi->depth_stencil_format;
- else
- stencilFormat = PIPE_FORMAT_NONE;
-
- assert(fb->must_resize);
- assert(fb->width);
- assert(fb->height);
-
- fb->stfb = st_create_framebuffer(
- &fb->visual,
- colorFormat,
- depthFormat,
- stencilFormat,
- fb->width,
- fb->height,
- (void *) fb );
-
- // to notify the context
- fb->must_resize = TRUE;
+ if (fb)
+ fb->refcnt++;
+ if (old_fb) {
+ pipe_mutex_lock(stw_dev->fb_mutex);
+
+ pipe_mutex_lock(old_fb->mutex);
+ stw_framebuffer_destroy_locked(old_fb);
+
+ pipe_mutex_unlock(stw_dev->fb_mutex);
}
-
- return fb->stfb ? TRUE : FALSE;
+
+ *ptr = fb;
}
* to know of their existing without using the not very portable PSAPI.
*/
stw_framebuffer_get_size(fb);
-
- if(fb->must_resize) {
- st_resize_framebuffer(fb->stfb, fb->width, fb->height);
- fb->must_resize = FALSE;
- }
}
}
stw_framebuffer_update(fb);
+ stw_notify_current_locked(fb);
stw_framebuffer_release(fb);
data.rect = fb->client_rect;
data.pPrivateData = (void *)surface;
+ stw_notify_current_locked(fb);
stw_framebuffer_release(fb);
return stw_dev->callbacks.wglCbPresentBuffers(hdc, &data);
stw_dev->stw_winsys->present( screen, surface, hdc );
stw_framebuffer_update(fb);
-
+ stw_notify_current_locked(fb);
stw_framebuffer_release(fb);
return TRUE;
HDC hdc )
{
struct stw_framebuffer *fb;
- struct pipe_surface *surface = NULL;
if (!stw_dev)
return FALSE;
return TRUE;
}
- st_swapbuffers(fb->stfb, &surface, NULL);
+ stw_flush_current_locked(fb);
- return stw_framebuffer_present_locked(hdc, fb, surface);
+ return stw_st_swap_framebuffer_locked(fb->stfb);
}
#include <windows.h>
-#include "main/mtypes.h"
-
#include "os/os_thread.h"
struct pipe_surface;
+struct st_framebuffer_iface;
struct stw_pixelformat_info;
/**
int iPixelFormat;
const struct stw_pixelformat_info *pfi;
- GLvisual visual;
+
+ struct st_framebuffer_iface *stfb;
/*
* Mutable members.
*/
- struct st_framebuffer *stfb;
+ unsigned refcnt;
+
/* FIXME: Make this work for multiple contexts bound to the same framebuffer */
boolean must_resize;
HDC hdc,
int iPixelFormat );
+void
+stw_framebuffer_reference(
+ struct stw_framebuffer **ptr,
+ struct stw_framebuffer *fb);
+
/**
* Search a framebuffer with a matching HWND.
*
stw_framebuffer_from_hdc(
HDC hdc );
-BOOL
-stw_framebuffer_allocate(
- struct stw_framebuffer *fb );
-
BOOL
stw_framebuffer_present_locked(HDC hdc,
struct stw_framebuffer *fb,
memset(pfi, 0, sizeof *pfi);
- pfi->color_format = color->format;
- pfi->depth_stencil_format = depth->format;
-
pfi->pfd.nSize = sizeof pfi->pfd;
pfi->pfd.nVersion = 1;
pfi->pfd.dwVisibleMask = 0;
pfi->pfd.dwDamageMask = 0;
- if(samples) {
- pfi->numSampleBuffers = 1;
- pfi->numSamples = samples;
- extended = TRUE;
- }
+ /*
+ * since state trackers can allocate depth/stencil/accum buffers, we provide
+ * only color buffers here
+ */
+ pfi->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
+ if (doublebuffer)
+ pfi->stvis.buffer_mask = ST_ATTACHMENT_BACK_LEFT_MASK;
+
+ pfi->stvis.color_format = color->format;
+ pfi->stvis.depth_stencil_format = depth->format;
+
+ pfi->stvis.accum_format = (accum) ?
+ PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
+
+ pfi->stvis.samples = samples;
+ pfi->stvis.render_buffer = ST_ATTACHMENT_INVALID;
++stw_dev->pixelformat_extended_count;
}
-void
-stw_pixelformat_visual(GLvisual *visual,
- const struct stw_pixelformat_info *pfi )
-{
- memset(visual, 0, sizeof *visual);
- _mesa_initialize_visual(
- visual,
- (pfi->pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE,
- (pfi->pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE,
- pfi->pfd.cRedBits,
- pfi->pfd.cGreenBits,
- pfi->pfd.cBlueBits,
- pfi->pfd.cAlphaBits,
- pfi->pfd.cDepthBits,
- pfi->pfd.cStencilBits,
- pfi->pfd.cAccumRedBits,
- pfi->pfd.cAccumGreenBits,
- pfi->pfd.cAccumBlueBits,
- pfi->pfd.cAccumAlphaBits,
- pfi->numSamples );
-}
-
-
LONG APIENTRY
DrvDescribePixelFormat(
HDC hdc,
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
+#include "state_tracker/st_api.h"
struct stw_pixelformat_info
{
- enum pipe_format color_format;
- enum pipe_format depth_stencil_format;
-
PIXELFORMATDESCRIPTOR pfd;
- unsigned numSampleBuffers;
- unsigned numSamples;
+ struct st_visual stvis;
};
void
const struct stw_pixelformat_info *
stw_pixelformat_get_info( uint index );
-void
-stw_pixelformat_visual(GLvisual *visual,
- const struct stw_pixelformat_info *pfi );
-
int
stw_pixelformat_choose( HDC hdc,
CONST PIXELFORMATDESCRIPTOR *ppfd );
--- /dev/null
+/*
+ * 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 <olv@lunarg.com>
+ */
+
+#include "util/u_memory.h"
+#include "util/u_inlines.h"
+#include "state_tracker/st_manager.h" /* for st_manager_create_api */
+
+#include "stw_st.h"
+#include "stw_device.h"
+#include "stw_framebuffer.h"
+#include "stw_pixelformat.h"
+
+struct stw_st_framebuffer {
+ struct st_framebuffer_iface base;
+
+ struct stw_framebuffer *fb;
+ struct st_visual stvis;
+
+ struct pipe_texture *textures[ST_ATTACHMENT_COUNT];
+ unsigned texture_width, texture_height;
+ unsigned texture_mask;
+
+ struct pipe_surface *front_surface, *back_surface;
+};
+
+static INLINE struct stw_st_framebuffer *
+stw_st_framebuffer(struct st_framebuffer_iface *stfb)
+{
+ return (struct stw_st_framebuffer *) stfb;
+}
+
+/**
+ * Remove outdated textures and create the requested ones.
+ */
+static void
+stw_st_framebuffer_validate_locked(struct st_framebuffer_iface *stfb,
+ unsigned width, unsigned height,
+ unsigned mask)
+{
+ struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
+ struct pipe_texture templ;
+ unsigned i;
+
+ /* remove outdated textures */
+ if (stwfb->texture_width != width || stwfb->texture_height != height) {
+ for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
+ pipe_texture_reference(&stwfb->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 (stwfb->textures[i] || !(mask & (1 << i))) {
+ /* remember the texture */
+ if (stwfb->textures[i])
+ mask |= (1 << i);
+ continue;
+ }
+
+ switch (i) {
+ case ST_ATTACHMENT_FRONT_LEFT:
+ case ST_ATTACHMENT_BACK_LEFT:
+ format = stwfb->stvis.color_format;
+ tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ break;
+ case ST_ATTACHMENT_DEPTH_STENCIL:
+ format = stwfb->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;
+
+ stwfb->textures[i] =
+ stw_dev->screen->texture_create(stw_dev->screen, &templ);
+ }
+ }
+
+ stwfb->texture_width = width;
+ stwfb->texture_height = height;
+ stwfb->texture_mask = mask;
+}
+
+static boolean
+stw_st_framebuffer_validate(struct st_framebuffer_iface *stfb,
+ const enum st_attachment_type *statts,
+ unsigned count,
+ struct pipe_texture **out)
+{
+ struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
+ unsigned statt_mask, i;
+
+ statt_mask = 0x0;
+ for (i = 0; i < count; i++)
+ statt_mask |= 1 << statts[i];
+
+ pipe_mutex_lock(stwfb->fb->mutex);
+
+ if (stwfb->fb->must_resize || (statt_mask & ~stwfb->texture_mask)) {
+ stw_st_framebuffer_validate_locked(&stwfb->base,
+ statt_mask, stwfb->fb->width, stwfb->fb->height);
+ stwfb->fb->must_resize = FALSE;
+ }
+
+ for (i = 0; i < count; i++) {
+ out[i] = NULL;
+ pipe_texture_reference(&out[i], stwfb->textures[statts[i]]);
+ }
+
+ stw_framebuffer_release(stwfb->fb);
+
+ return TRUE;
+}
+
+static struct pipe_surface *
+get_present_surface_locked(struct st_framebuffer_iface *stfb,
+ enum st_attachment_type statt)
+{
+ struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
+ struct pipe_texture *ptex;
+ struct pipe_surface *psurf, **cache;
+
+ ptex = stwfb->textures[statt];
+ if (!ptex)
+ return NULL;
+
+ psurf = NULL;
+
+ switch (statt) {
+ case ST_ATTACHMENT_FRONT_LEFT:
+ cache = &stwfb->front_surface;
+ break;
+ case ST_ATTACHMENT_BACK_LEFT:
+ cache = &stwfb->back_surface;
+ break;
+ default:
+ cache = &psurf;
+ break;
+ }
+
+ if (!*cache) {
+ *cache = stw_dev->screen->get_tex_surface(stw_dev->screen,
+ ptex, 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ);
+ }
+
+ if (psurf != *cache)
+ pipe_surface_reference(&psurf, *cache);
+
+ return psurf;
+}
+
+/**
+ * Present an attachment of the framebuffer.
+ */
+static boolean
+stw_st_framebuffer_present_locked(struct st_framebuffer_iface *stfb,
+ enum st_attachment_type statt)
+{
+ struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
+ struct pipe_surface *psurf;
+
+ psurf = get_present_surface_locked(&stwfb->base, statt);
+ if (psurf) {
+ stw_framebuffer_present_locked(stwfb->fb->hDC, stwfb->fb, psurf);
+ pipe_surface_reference(&psurf, NULL);
+ }
+
+ return TRUE;
+}
+
+static boolean
+stw_st_framebuffer_flush_front(struct st_framebuffer_iface *stfb,
+ enum st_attachment_type statt)
+{
+ struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
+
+ pipe_mutex_lock(stwfb->fb->mutex);
+
+ return stw_st_framebuffer_present_locked(&stwfb->base, statt);
+}
+
+/**
+ * Create a framebuffer interface.
+ */
+struct st_framebuffer_iface *
+stw_st_create_framebuffer(struct stw_framebuffer *fb)
+{
+ struct stw_st_framebuffer *stwfb;
+
+ stwfb = CALLOC_STRUCT(stw_st_framebuffer);
+ if (!stwfb)
+ return NULL;
+
+ stwfb->fb = fb;
+ stwfb->stvis = fb->pfi->stvis;
+
+ stwfb->base.visual = &stwfb->stvis;
+ stwfb->base.flush_front = stw_st_framebuffer_flush_front;
+ stwfb->base.validate = stw_st_framebuffer_validate;
+
+ return &stwfb->base;
+}
+
+/**
+ * Destroy a framebuffer interface.
+ */
+void
+stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb)
+{
+ struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
+ int i;
+
+ pipe_surface_reference(&stwfb->front_surface, NULL);
+ pipe_surface_reference(&stwfb->back_surface, NULL);
+
+ for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
+ pipe_texture_reference(&stwfb->textures[i], NULL);
+
+ FREE(stwfb);
+}
+
+/**
+ * Swap the buffers of the given framebuffer.
+ */
+boolean
+stw_st_swap_framebuffer_locked(struct st_framebuffer_iface *stfb)
+{
+ struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
+ unsigned front = ST_ATTACHMENT_FRONT_LEFT, back = ST_ATTACHMENT_BACK_LEFT;
+ struct pipe_texture *ptex;
+ struct pipe_surface *psurf;
+ unsigned mask;
+
+ /* swap the textures */
+ ptex = stwfb->textures[front];
+ stwfb->textures[front] = stwfb->textures[back];
+ stwfb->textures[back] = ptex;
+
+ /* swap the surfaces */
+ psurf = stwfb->front_surface;
+ stwfb->front_surface = stwfb->back_surface;
+ stwfb->back_surface = psurf;
+
+ /* convert to mask */
+ front = 1 << front;
+ back = 1 << back;
+
+ /* swap the bits in mask */
+ mask = stwfb->texture_mask & ~(front | back);
+ if (stwfb->texture_mask & front)
+ mask |= back;
+ if (stwfb->texture_mask & back)
+ mask |= front;
+ stwfb->texture_mask = mask;
+
+ front = ST_ATTACHMENT_FRONT_LEFT;
+ return stw_st_framebuffer_present_locked(&stwfb->base, front);
+}
+
+/**
+ * Create an st_api of the state tracker.
+ */
+struct st_api *
+stw_st_create_api(void)
+{
+ return st_manager_create_api();
+}
--- /dev/null
+/*
+ * 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 <olv@lunarg.com>
+ */
+
+#ifndef STW_ST_H
+#define STW_ST_H
+
+#include "state_tracker/st_api.h"
+
+struct stw_framebuffer;
+
+struct st_api *
+stw_st_create_api(void);
+
+struct st_framebuffer_iface *
+stw_st_create_framebuffer(struct stw_framebuffer *fb);
+
+void
+stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb);
+
+boolean
+stw_st_swap_framebuffer_locked(struct st_framebuffer_iface *stfb);
+
+#endif /* STW_ST_H */