Module: wine
Branch: master
Commit: 19b6f5ca75b43f61a366aa521eab9ddbfc4f99dd
URL: http://source.winehq.org/git/wine.git/?a=commit;h=19b6f5ca75b43f61a366aa521…
Author: Stefan Dösinger <stefan(a)codeweavers.com>
Date: Sun Mar 28 16:25:04 2010 +0200
wined3d: Control the onscreen depth stencil format in the swapchain.
This allows the swapchain to know what depth format its window contexts have to see if the
requested depth format is compatible or a FBO fallback is needed, and it will be needed to
set the onscreen format to the requested auto depth stencil format instead of the
let's-hope-it-fits D24_UNORM_S8_UINT format.
---
dlls/wined3d/context.c | 22 ++--------------------
dlls/wined3d/device.c | 2 +-
dlls/wined3d/swapchain.c | 25 +++++++++++++++++++++++--
dlls/wined3d/wined3d_private.h | 4 +++-
4 files changed, 29 insertions(+), 24 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index f3729ae..738746e 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1087,23 +1087,6 @@ static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc,
return 0;
}
- /* In WGL both color, depth and stencil are features of a pixel format. In case of D3D they are separate.
- * You are able to add a depth + stencil surface at a later stage when you need it.
- * In order to support this properly in WineD3D we need the ability to recreate the opengl context and
- * drawable when this is required. This is very tricky as we need to reapply ALL opengl states for the new
- * context, need torecreate shaders, textures and other resources.
- *
- * The context manager already takes care of the state problem and for the other tasks code from Reset
- * can be used. These changes are way to risky during the 1.0 code freeze which is taking place right now.
- * Likely a lot of other new bugs will be exposed. For that reason request a depth stencil surface all the
- * time. It can cause a slight performance hit but fixes a lot of regressions. A fixme reminds of that this
- * issue needs to be fixed. */
- if (ds_format_desc->format != WINED3DFMT_D24_UNORM_S8_UINT)
- {
- FIXME("Add OpenGL context recreation support to SetDepthStencilSurface\n");
- ds_format_desc = getFormatDescEntry(WINED3DFMT_D24_UNORM_S8_UINT, &This->adapter->gl_info);
- }
-
getDepthStencilBits(ds_format_desc, &depthBits, &stencilBits);
for(matchtry = 0; matchtry < (sizeof(matches) / sizeof(matches[0])) && !iPixelFormat; matchtry++) {
@@ -1229,12 +1212,12 @@ static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc,
* pPresentParameters: contains the pixelformats to use for onscreen rendering
*
*****************************************************************************/
-struct wined3d_context *context_create(IWineD3DSwapChainImpl *swapchain, IWineD3DSurfaceImpl *target)
+struct wined3d_context *context_create(IWineD3DSwapChainImpl *swapchain, IWineD3DSurfaceImpl *target,
+ const struct wined3d_format_desc *ds_format_desc)
{
IWineD3DDeviceImpl *device = swapchain->device;
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
const struct wined3d_format_desc *color_format_desc;
- const struct wined3d_format_desc *ds_format_desc;
struct wined3d_context *ret;
PIXELFORMATDESCRIPTOR pfd;
BOOL auxBuffers = FALSE;
@@ -1260,7 +1243,6 @@ struct wined3d_context *context_create(IWineD3DSwapChainImpl *swapchain, IWineD3
goto out;
}
- ds_format_desc = getFormatDescEntry(WINED3DFMT_UNKNOWN, gl_info);
color_format_desc = target->resource.format_desc;
/* In case of ORM_BACKBUFFER, make sure to request an alpha component for
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index aa16118..06e95f0 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -6318,7 +6318,7 @@ HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain *
}
target = (IWineD3DSurfaceImpl *)(swapchain->backBuffer ? swapchain->backBuffer[0] : swapchain->frontBuffer);
- if (!(context = context_create(swapchain, target)))
+ if (!(context = context_create(swapchain, target, swapchain->ds_format)))
{
WARN("Failed to create context.\n");
HeapFree(GetProcessHeap(), 0, swapchain->context);
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index bd44b03..14a741b 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -795,7 +795,28 @@ HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface
if (surface_type == SURFACE_OPENGL)
{
- if (!(swapchain->context[0] = context_create(swapchain, (IWineD3DSurfaceImpl *)swapchain->frontBuffer)))
+ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+
+ /* In WGL both color, depth and stencil are features of a pixel format. In case of D3D they are separate.
+ * You are able to add a depth + stencil surface at a later stage when you need it.
+ * In order to support this properly in WineD3D we need the ability to recreate the opengl context and
+ * drawable when this is required. This is very tricky as we need to reapply ALL opengl states for the new
+ * context, need torecreate shaders, textures and other resources.
+ *
+ * The context manager already takes care of the state problem and for the other tasks code from Reset
+ * can be used. These changes are way to risky during the 1.0 code freeze which is taking place right now.
+ * Likely a lot of other new bugs will be exposed. For that reason request a depth stencil surface all the
+ * time. It can cause a slight performance hit but fixes a lot of regressions. A fixme reminds of that this
+ * issue needs to be fixed. */
+ if (!present_parameters->EnableAutoDepthStencil
+ || swapchain->presentParms.AutoDepthStencilFormat != WINED3DFMT_D24_UNORM_S8_UINT)
+ {
+ FIXME("Add OpenGL context recreation support to SetDepthStencilSurface\n");
+ }
+ swapchain->ds_format = getFormatDescEntry(WINED3DFMT_D24_UNORM_S8_UINT, gl_info);
+ swapchain->context[0] = context_create(swapchain, (IWineD3DSurfaceImpl *)swapchain->frontBuffer,
+ swapchain->ds_format);
+ if (!swapchain->context[0])
{
WARN("Failed to create context.\n");
hr = WINED3DERR_NOTAVAILABLE;
@@ -912,7 +933,7 @@ struct wined3d_context *swapchain_create_context_for_thread(IWineD3DSwapChain *i
TRACE("Creating a new context for swapchain %p, thread %d\n", This, GetCurrentThreadId());
- if (!(ctx = context_create(This, (IWineD3DSurfaceImpl *)This->frontBuffer)))
+ if (!(ctx = context_create(This, (IWineD3DSurfaceImpl *)This->frontBuffer, This->ds_format)))
{
ERR("Failed to create a new context for the swapchain\n");
return NULL;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index eb9ae9f..a812114 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1204,7 +1204,8 @@ void context_attach_depth_stencil_fbo(struct wined3d_context *context,
GLenum fbo_target, IWineD3DSurface *depth_stencil, BOOL use_render_buffer) DECLSPEC_HIDDEN;
void context_attach_surface_fbo(const struct wined3d_context *context,
GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) DECLSPEC_HIDDEN;
-struct wined3d_context *context_create(IWineD3DSwapChainImpl *swapchain, IWineD3DSurfaceImpl *target) DECLSPEC_HIDDEN;
+struct wined3d_context *context_create(IWineD3DSwapChainImpl *swapchain, IWineD3DSurfaceImpl *target,
+ const struct wined3d_format_desc *ds_format_desc) DECLSPEC_HIDDEN;
void context_destroy(IWineD3DDeviceImpl *This, struct wined3d_context *context) DECLSPEC_HIDDEN;
void context_free_event_query(struct wined3d_event_query *query) DECLSPEC_HIDDEN;
void context_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN;
@@ -2556,6 +2557,7 @@ struct IWineD3DSwapChainImpl
WINED3DFORMAT orig_fmt;
WINED3DGAMMARAMP orig_gamma;
BOOL render_to_fbo;
+ const struct wined3d_format_desc *ds_format;
long prev_time, frames; /* Performance tracking */
unsigned int vSyncCounter;
Module: wine
Branch: master
Commit: a4b0bedc30f31d19d969364c80f979b77cce9011
URL: http://source.winehq.org/git/wine.git/?a=commit;h=a4b0bedc30f31d19d969364c8…
Author: Stefan Dösinger <stefan(a)codeweavers.com>
Date: Sat Mar 27 17:40:28 2010 +0100
wined3d: Split out offscreen rendering concerns from FindContext.
---
dlls/wined3d/context.c | 163 ++++++++++++++++++++++++-----------------------
1 files changed, 83 insertions(+), 80 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 15a8f77..f3729ae 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1834,10 +1834,8 @@ static struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSur
{
IWineD3DSwapChain *swapchain = NULL;
struct wined3d_context *current_context = context_get_current();
- const struct StateEntry *StateTable = This->StateTable;
DWORD tid = GetCurrentThreadId();
struct wined3d_context *context;
- BOOL old_render_offscreen;
if (current_context && current_context->destroyed) current_context = NULL;
@@ -1867,9 +1865,6 @@ static struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSur
TRACE("Rendering onscreen\n");
context = findThreadContextForSwapChain(swapchain, tid);
-
- old_render_offscreen = context->render_offscreen;
- context->render_offscreen = surface_is_offscreen(target);
IWineD3DSwapChain_Release(swapchain);
}
else
@@ -1891,85 +1886,10 @@ static struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSur
* is perfect to call. */
context = findThreadContextForSwapChain(This->swapchains[0], tid);
}
-
- old_render_offscreen = context->render_offscreen;
- context->render_offscreen = TRUE;
}
context_validate(context);
- if (context->render_offscreen != old_render_offscreen)
- {
- Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION), StateTable);
- Context_MarkStateDirty(context, STATE_VDECL, StateTable);
- Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable);
- Context_MarkStateDirty(context, STATE_SCISSORRECT, StateTable);
- Context_MarkStateDirty(context, STATE_FRONTFACE, StateTable);
- }
-
- /* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers
- * the alpha blend state changes with different render target formats. */
- if (!context->current_rt)
- {
- Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
- }
- else
- {
- const struct wined3d_format_desc *old = ((IWineD3DSurfaceImpl *)context->current_rt)->resource.format_desc;
- const struct wined3d_format_desc *new = ((IWineD3DSurfaceImpl *)target)->resource.format_desc;
-
- if (old->format != new->format)
- {
- /* Disable blending when the alpha mask has changed and when a format doesn't support blending. */
- if ((old->alpha_mask && !new->alpha_mask) || (!old->alpha_mask && new->alpha_mask)
- || !(new->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
- {
- Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
- }
- }
-
- /* When switching away from an offscreen render target, and we're not
- * using FBOs, we have to read the drawable into the texture. This is
- * done via PreLoad (and SFLAG_INDRAWABLE set on the surface). There
- * are some things that need care though. PreLoad needs a GL context,
- * and FindContext is called before the context is activated. It also
- * has to be called with the old rendertarget active, otherwise a
- * wrong drawable is read. */
- if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
- && old_render_offscreen && context->current_rt != target)
- {
- BOOL oldInDraw = This->isInDraw;
-
- /* surface_internal_preload() requires a context to load the
- * texture, so it will call context_acquire(). Set isInDraw to true
- * to signal surface_internal_preload() that it has a context. */
-
- /* FIXME: This is just broken. There's no guarantee whatsoever
- * that the currently active context, if any, is appropriate for
- * reading back the render target. We should probably call
- * context_set_current(context) here and then rely on
- * context_acquire() doing the right thing. */
- This->isInDraw = TRUE;
-
- /* Read the back buffer of the old drawable into the destination texture. */
- if (((IWineD3DSurfaceImpl *)context->current_rt)->texture_name_srgb)
- {
- surface_internal_preload(context->current_rt, SRGB_BOTH);
- }
- else
- {
- surface_internal_preload(context->current_rt, SRGB_RGB);
- }
-
- IWineD3DSurface_ModifyLocation(context->current_rt, SFLAG_INDRAWABLE, FALSE);
-
- This->isInDraw = oldInDraw;
- }
- }
-
- context->draw_buffer_dirty = TRUE;
- context->current_rt = target;
-
return context;
}
@@ -2139,6 +2059,88 @@ static void context_apply_state(struct wined3d_context *context, IWineD3DDeviceI
}
}
+static void context_setup_target(IWineD3DDeviceImpl *device, struct wined3d_context *context, IWineD3DSurface *target)
+{
+ BOOL old_render_offscreen = context->render_offscreen;
+ const struct StateEntry *StateTable = device->StateTable;
+
+ if (!target) return;
+ else if (context->current_rt == target) return;
+ context->render_offscreen = surface_is_offscreen(target);
+
+ if (context->render_offscreen != old_render_offscreen)
+ {
+ Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION), StateTable);
+ Context_MarkStateDirty(context, STATE_VDECL, StateTable);
+ Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable);
+ Context_MarkStateDirty(context, STATE_SCISSORRECT, StateTable);
+ Context_MarkStateDirty(context, STATE_FRONTFACE, StateTable);
+ }
+
+ /* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers
+ * the alpha blend state changes with different render target formats. */
+ if (!context->current_rt)
+ {
+ Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
+ }
+ else
+ {
+ const struct wined3d_format_desc *old = ((IWineD3DSurfaceImpl *)context->current_rt)->resource.format_desc;
+ const struct wined3d_format_desc *new = ((IWineD3DSurfaceImpl *)target)->resource.format_desc;
+
+ if (old->format != new->format)
+ {
+ /* Disable blending when the alpha mask has changed and when a format doesn't support blending. */
+ if ((old->alpha_mask && !new->alpha_mask) || (!old->alpha_mask && new->alpha_mask)
+ || !(new->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
+ {
+ Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
+ }
+ }
+
+ /* When switching away from an offscreen render target, and we're not
+ * using FBOs, we have to read the drawable into the texture. This is
+ * done via PreLoad (and SFLAG_INDRAWABLE set on the surface). There
+ * are some things that need care though. PreLoad needs a GL context,
+ * and FindContext is called before the context is activated. It also
+ * has to be called with the old rendertarget active, otherwise a
+ * wrong drawable is read. */
+ if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+ && old_render_offscreen && context->current_rt != target)
+ {
+ BOOL oldInDraw = device->isInDraw;
+
+ /* surface_internal_preload() requires a context to load the
+ * texture, so it will call context_acquire(). Set isInDraw to true
+ * to signal surface_internal_preload() that it has a context. */
+
+ /* FIXME: This is just broken. There's no guarantee whatsoever
+ * that the currently active context, if any, is appropriate for
+ * reading back the render target. We should probably call
+ * context_set_current(context) here and then rely on
+ * context_acquire() doing the right thing. */
+ device->isInDraw = TRUE;
+
+ /* Read the back buffer of the old drawable into the destination texture. */
+ if (((IWineD3DSurfaceImpl *)context->current_rt)->texture_name_srgb)
+ {
+ surface_internal_preload(context->current_rt, SRGB_BOTH);
+ }
+ else
+ {
+ surface_internal_preload(context->current_rt, SRGB_RGB);
+ }
+
+ IWineD3DSurface_ModifyLocation(context->current_rt, SFLAG_INDRAWABLE, FALSE);
+
+ device->isInDraw = oldInDraw;
+ }
+ }
+
+ context->draw_buffer_dirty = TRUE;
+ context->current_rt = target;
+}
+
/*****************************************************************************
* context_acquire
*
@@ -2160,6 +2162,7 @@ struct wined3d_context *context_acquire(IWineD3DDeviceImpl *device, IWineD3DSurf
TRACE("device %p, target %p, usage %#x.\n", device, target, usage);
context = FindContext(device, target);
+ context_setup_target(device, context, target);
context_enter(context);
if (!context->valid) return context;