context.c revision 4237d5a79f48789aacc67dc43378d2d7813a39f4
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * Context and render target management in wined3d
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * Copyright 2007-2011, 2013 Stefan Dösinger for CodeWeavers
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * Copyright 2009-2011 Henri Verbeet for CodeWeavers
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * This library is free software; you can redistribute it and/or
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * modify it under the terms of the GNU Lesser General Public
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * License as published by the Free Software Foundation; either
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * version 2.1 of the License, or (at your option) any later version.
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * This library is distributed in the hope that it will be useful,
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * but WITHOUT ANY WARRANTY; without even the implied warranty of
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * Lesser General Public License for more details.
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * You should have received a copy of the GNU Lesser General Public
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * License along with this library; if not, write to the Free Software
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * a choice of LGPL license versions is made available with the language indicating
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * that LGPLv2 or any later version may be used, or where a choice of which version
072f0b86f23a38efb7454da3144cbce76805be76vboxsync * of the LGPL is applied is otherwise unspecified.
072f0b86f23a38efb7454da3144cbce76805be76vboxsync#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
072f0b86f23a38efb7454da3144cbce76805be76vboxsync# define vboxGetCurrentContext() VBoxTlsRefGetCurrent(struct wined3d_context, wined3d_context_tls_idx)
072f0b86f23a38efb7454da3144cbce76805be76vboxsync# define vboxSetCurrentContext(_ctx) VBoxTlsRefSetCurrent(struct wined3d_context, wined3d_context_tls_idx, (_ctx))
072f0b86f23a38efb7454da3144cbce76805be76vboxsync/* FBO helper functions */
072f0b86f23a38efb7454da3144cbce76805be76vboxsync/* Context activation is done by the caller. */
072f0b86f23a38efb7454da3144cbce76805be76vboxsyncstatic void context_bind_fbo(struct wined3d_context *context, GLenum target, GLuint fbo)
072f0b86f23a38efb7454da3144cbce76805be76vboxsync const struct wined3d_gl_info *gl_info = context->gl_info;
case GL_FRAMEBUFFER:
if (depth_stencil)
switch (location)
case SFLAG_INTEXTURE:
case SFLAG_INSRGBTEX:
case SFLAG_INRB_MULTISAMPLE:
case SFLAG_INRB_RESOLVED:
switch (location)
case SFLAG_INTEXTURE:
case SFLAG_INSRGBTEX:
case SFLAG_INRB_MULTISAMPLE:
case SFLAG_INRB_RESOLVED:
gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx, GL_TEXTURE_2D, 0, 0);
if (attachment)
if (attachment)
entry->render_targets = HeapAlloc(GetProcessHeap(), 0, gl_info->limits.buffers * sizeof(*entry->render_targets));
memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets));
return entry;
memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets));
return entry;
return entry;
static void context_apply_fbo_entry(struct wined3d_context *context, GLenum target, struct fbo_entry *entry)
context->current_fbo = context_find_fbo_entry(context, target, render_targets, depth_stencil, location);
if (clear_size)
void context_alloc_occlusion_query(struct wined3d_context *context, struct wined3d_occlusion_query *query)
if (!new_data)
union wined3d_gl_query_object *new_data = HeapReAlloc(GetProcessHeap(), 0, context->free_event_queries,
if (!new_data)
UINT i;
UINT j;
static void context_queue_fbo_entry_destruction(struct wined3d_context *context, struct fbo_entry *entry)
switch (type)
case WINED3D_RTYPE_SURFACE:
switch (type)
case WINED3D_RTYPE_SURFACE:
#ifndef VBOX
if (!current)
return FALSE;
return TRUE;
return FALSE;
return TRUE;
return TRUE;
#ifndef VBOX
#ifndef VBOX_WITH_WDDM
#ifndef VBOX
return FALSE;
#ifndef VBOX_WITH_WDDM
return FALSE;
#ifndef VBOX
return FALSE;
return FALSE;
return FALSE;
return TRUE;
static void context_restore_gl_context(const struct wined3d_gl_info *gl_info, HDC dc, HGLRC gl_ctx, int pf)
#ifndef VBOX
#ifdef VBOX
UINT i = 0;
return FALSE;
# if defined(VBOX_WITH_WDDM)
ERR("Unexpected swapchain for dc %p window expected %p, but was %p.\n", swapchain->hDC, swapchain->win_handle, hWnd);
ERR("Swapchain for dc %p window expected %p, but was %p.\n", swapchain->hDC, swapchain->win_handle, hWnd);
return FALSE;
return TRUE;
if (context)
return swapchain;
return NULL;
if (swapchain)
return swapchain;
return swapchain;
struct wined3d_surface *target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer;
#ifdef VBOX_WITH_WDDM
if(!context)
if(!context)
return context;
goto err;
#ifndef VBOX
#ifndef VBOX
goto err;
#ifndef VBOX
goto err;
err:
if (!swapchain)
int restore_pf;
#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
LIST_FOR_EACH_ENTRY(occlusion_query, &context->occlusion_queries, struct wined3d_occlusion_query, entry)
else if (gl_info->supported[APPLE_FENCE]) GL_EXTCALL(glDeleteFencesAPPLE(1, &event_query->object.id));
GL_EXTCALL(glDeleteQueriesARB(context->free_occlusion_query_count, context->free_occlusion_queries));
if (restore_ctx)
#ifndef VBOX_WITH_WDDM
# ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
# ifndef VBOX
return wined3d_context_tls_idx;
return NULL;
if (!adjustTid)
return ctx;
return ctx;
/* the context may have cleared swapchain (if swapchain was destroyed), ensure it has some valid swapchain set */
return ctx;
return NULL;
return TRUE;
if (old)
if (ctx)
return FALSE;
#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
TRACE("Switching to D3D context %p, GL context %p, device context %p.\n", ctx, ctx->glCtx, ctx->hdc);
TRACE("Switching to D3D context %p, GL context %p, device context %p.\n", ctx, ctx->glCtx, ctx->swapchain->hDC);
return FALSE;
else if(wglGetCurrentContext())
return FALSE;
if (ctx)
return TRUE;
if (!old)
// * 2. now increase its ref count to ensure its dtor routine is not called while making set_current(NULL).
TRACE("Restoring GL context %p on device context %p.\n", context->restore_ctx, context->restore_dc);
context_restore_gl_context(context->gl_info, context->restore_dc, context->restore_ctx, context->restore_pf);
int iPixelFormat=0;
unsigned int current_value;
current_value = 0;
for (i = 0; i < cfg_count; ++i)
unsigned int value;
/* When findCompatible is set and no suitable format was found, let ChoosePixelFormat choose a pixel format in order not to crash. */
return FALSE;
} else if(!iPixelFormat) {
TRACE("Falling back to ChoosePixelFormat as we weren't able to find an exactly matching pixel format\n");
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
if(!iPixelFormat) {
return FALSE;
return iPixelFormat;
static void bind_dummy_textures(const struct wined3d_device *device, const struct wined3d_context *context)
for (i = 0; i < count; ++i)
switch (type)
case GL_DEBUG_TYPE_ERROR_ARB:
#ifdef VBOX_WITH_WDDM
int pixel_format;
int swap_interval;
#ifdef VBOX_WITH_WDDM
if (!pHgsmi)
return NULL;
if (!ret)
return NULL;
goto out;
goto out;
goto out;
goto out;
goto out;
goto out;
pixel_format = context_choose_pixel_format(device, hdc, color_format, ds_format, auxBuffers, FALSE);
if (!pixel_format)
/* If we still don't have a pixel format, something is very wrong as ChoosePixelFormat barely fails */
if (!pixel_format)
goto out;
#ifndef VBOX
goto out;
unsigned int ctx_attrib_idx = 0;
goto out;
#ifdef VBOX_WITH_WDDM
, pHgsmi
, NULL
if (!ctx)
goto out;
#ifndef VBOX
goto out;
goto out;
goto out;
swap_interval = 0;
#ifdef VBOX
* this is a kinda hack, but it is needed since our ogl driver currently does not support ShareLists */
# if defined(VBOX_WITH_WDDM)
* GLSL should bypass this. This causes problems in programs that never use the fixed function pipeline,
const char *dummy_program =
"MOV result.color, fragment.color.primary;\n"
GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(dummy_program), dummy_program));
return ret;
out:
return NULL;
#ifdef DEBUG_misha
if (!rt_mask)
while (rt_mask)
DWORD *current_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
void context_active_texture(struct wined3d_context *context, const struct wined3d_gl_info *gl_info, unsigned int unit)
if (name)
switch (old_texture_type)
case GL_NONE:
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE_ARB:
case GL_TEXTURE_CUBE_MAP:
case GL_TEXTURE_3D:
if ((existing->flags & WINED3DFMT_FLAG_FLOAT) != (required->flags & WINED3DFMT_FLAG_FLOAT)) return FALSE;
return TRUE;
/* The currently active context is the necessary context to access the swapchain's onscreen buffers */
static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_device *device, const struct wined3d_surface *rt)
rt_mask = 0;
for (i = 0; i < rt_count; ++i)
return TRUE;
return FALSE;
BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_device *device,
UINT i;
return FALSE;
for (i = 0; i < rt_count; ++i)
for (i = 0; i < rt_count; ++i)
return TRUE;
static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const struct wined3d_device *device)
if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return context_generate_rt_mask_no_fbo(device, rts[0]);
while (rt_mask_bits)
return rt_mask;
void context_state_fb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
void context_state_drawbuf(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
return FALSE;
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && isStateDirty(context, STATE_FRAMEBUFFER))
return TRUE;
/* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers
struct wined3d_context *context_acquire(const struct wined3d_device *device, struct wined3d_surface *target)
if (!target)
if (current_context
#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
if (!swapchain)
#ifdef VBOX_WITH_WINE_DBG
#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
#ifndef VBOX_WINE_WITH_SINGLE_CONTEXT
if (!swapchain)
return context;