wined3d: Allow stencil support when it wasn't requested on broken drivers.
[wine] / dlls / wined3d / context.c
1 /*
2  * Context and render target management in wined3d
3  *
4  * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include <stdio.h>
23 #ifdef HAVE_FLOAT_H
24 # include <float.h>
25 #endif
26 #include "wined3d_private.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
29
30 #define GLINFO_LOCATION This->adapter->gl_info
31
32 /*****************************************************************************
33  * Context_MarkStateDirty
34  *
35  * Marks a state in a context dirty. Only one context, opposed to
36  * IWineD3DDeviceImpl_MarkStateDirty, which marks the state dirty in all
37  * contexts
38  *
39  * Params:
40  *  context: Context to mark the state dirty in
41  *  state: State to mark dirty
42  *  StateTable: Pointer to the state table in use(for state grouping)
43  *
44  *****************************************************************************/
45 static void Context_MarkStateDirty(WineD3DContext *context, DWORD state, const struct StateEntry *StateTable) {
46     DWORD rep = StateTable[state].representative;
47     DWORD idx;
48     BYTE shift;
49
50     if(!rep || isStateDirty(context, rep)) return;
51
52     context->dirtyArray[context->numDirtyEntries++] = rep;
53     idx = rep >> 5;
54     shift = rep & 0x1f;
55     context->isStateDirty[idx] |= (1 << shift);
56 }
57
58 /*****************************************************************************
59  * AddContextToArray
60  *
61  * Adds a context to the context array. Helper function for CreateContext
62  *
63  * This method is not called in performance-critical code paths, only when a
64  * new render target or swapchain is created. Thus performance is not an issue
65  * here.
66  *
67  * Params:
68  *  This: Device to add the context for
69  *  hdc: device context
70  *  glCtx: WGL context to add
71  *  pbuffer: optional pbuffer used with this context
72  *
73  *****************************************************************************/
74 static WineD3DContext *AddContextToArray(IWineD3DDeviceImpl *This, HWND win_handle, HDC hdc, HGLRC glCtx, HPBUFFERARB pbuffer) {
75     WineD3DContext **oldArray = This->contexts;
76     DWORD state;
77
78     This->contexts = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->contexts) * (This->numContexts + 1));
79     if(This->contexts == NULL) {
80         ERR("Unable to grow the context array\n");
81         This->contexts = oldArray;
82         return NULL;
83     }
84     if(oldArray) {
85         memcpy(This->contexts, oldArray, sizeof(*This->contexts) * This->numContexts);
86     }
87
88     This->contexts[This->numContexts] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineD3DContext));
89     if(This->contexts[This->numContexts] == NULL) {
90         ERR("Unable to allocate a new context\n");
91         HeapFree(GetProcessHeap(), 0, This->contexts);
92         This->contexts = oldArray;
93         return NULL;
94     }
95
96     This->contexts[This->numContexts]->hdc = hdc;
97     This->contexts[This->numContexts]->glCtx = glCtx;
98     This->contexts[This->numContexts]->pbuffer = pbuffer;
99     This->contexts[This->numContexts]->win_handle = win_handle;
100     HeapFree(GetProcessHeap(), 0, oldArray);
101
102     /* Mark all states dirty to force a proper initialization of the states on the first use of the context
103      */
104     for(state = 0; state <= STATE_HIGHEST; state++) {
105         Context_MarkStateDirty(This->contexts[This->numContexts], state, This->shader_backend->StateTable);
106     }
107
108     This->numContexts++;
109     TRACE("Created context %p\n", This->contexts[This->numContexts - 1]);
110     return This->contexts[This->numContexts - 1];
111 }
112
113 /* This function takes care of WineD3D pixel format selection. */
114 static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc, WINED3DFORMAT ColorFormat, WINED3DFORMAT DepthStencilFormat, BOOL auxBuffers, int numSamples, BOOL pbuffer, BOOL findCompatible)
115 {
116     int iPixelFormat=0;
117     short redBits, greenBits, blueBits, alphaBits, colorBits;
118     short depthBits=0, stencilBits=0;
119
120     int i = 0;
121     int nCfgs = This->adapter->nCfgs;
122     WineD3D_PixelFormat *cfgs = This->adapter->cfgs;
123
124     if(!getColorBits(ColorFormat, &redBits, &greenBits, &blueBits, &alphaBits, &colorBits)) {
125         ERR("Unable to get color bits for format %s (%#x)!\n", debug_d3dformat(ColorFormat), ColorFormat);
126         return 0;
127     }
128
129     if(DepthStencilFormat) {
130         getDepthStencilBits(DepthStencilFormat, &depthBits, &stencilBits);
131     }
132
133     /* Find a pixel format which EXACTLY matches our requirements (except for depth) */
134     for(i=0; i<nCfgs; i++) {
135         BOOL exactDepthMatch = TRUE;
136         cfgs = &This->adapter->cfgs[i];
137
138         /* For now only accept RGBA formats. Perhaps some day we will
139          * allow floating point formats for pbuffers. */
140         if(cfgs->iPixelType != WGL_TYPE_RGBA_ARB)
141             continue;
142
143         /* In window mode (!pbuffer) we need a window drawable format and double buffering. */
144         if(!pbuffer && !(cfgs->windowDrawable && cfgs->doubleBuffer))
145             continue;
146
147         /* We like to have aux buffers in backbuffer mode */
148         if(auxBuffers && !cfgs->auxBuffers)
149             continue;
150
151         /* In pbuffer-mode we need a pbuffer-capable format but we don't want double buffering */
152         if(pbuffer && (!cfgs->pbufferDrawable || cfgs->doubleBuffer))
153             continue;
154
155         if(cfgs->redSize != redBits)
156             continue;
157         if(cfgs->greenSize != greenBits)
158             continue;
159         if(cfgs->blueSize != blueBits)
160             continue;
161         if(cfgs->alphaSize != alphaBits)
162             continue;
163
164         /* We try to locate a format which matches our requirements exactly. In case of
165          * depth it is no problem to emulate 16-bit using e.g. 24-bit, so accept that. */
166         if(cfgs->depthSize < depthBits)
167             continue;
168         else if(cfgs->depthSize > depthBits)
169             exactDepthMatch = FALSE;
170
171         /* In all cases make sure the number of stencil bits matches our requirements
172          * even when we don't need stencil because it could affect performance EXCEPT
173          * on cards which don't offer depth formats without stencil like the i915 drivers
174          * on Linux. */
175         if(stencilBits != cfgs->stencilSize && !(This->adapter->brokenStencil && stencilBits <= cfgs->stencilSize))
176             continue;
177
178         /* Check multisampling support */
179         if(cfgs->numSamples != numSamples)
180             continue;
181
182         /* When we have passed all the checks then we have found a format which matches our
183          * requirements. Note that we only check for a limit number of capabilities right now,
184          * so there can easily be a dozen of pixel formats which appear to be the 'same' but
185          * can still differ in things like multisampling, stereo, SRGB and other flags.
186          */
187
188         /* Exit the loop as we have found a format :) */
189         if(exactDepthMatch) {
190             iPixelFormat = cfgs->iPixelFormat;
191             break;
192         } else if(!iPixelFormat) {
193             /* In the end we might end up with a format which doesn't exactly match our depth
194              * requirements. Accept the first format we found because formats with higher iPixelFormat
195              * values tend to have more extended capabilities (e.g. multisampling) which we don't need. */
196             iPixelFormat = cfgs->iPixelFormat;
197         }
198     }
199
200     /* When findCompatible is set and no suitable format was found, let ChoosePixelFormat choose a pixel format in order not to crash. */
201     if(!iPixelFormat && !findCompatible) {
202         ERR("Can't find a suitable iPixelFormat\n");
203         return FALSE;
204     } else if(!iPixelFormat) {
205         PIXELFORMATDESCRIPTOR pfd;
206
207         TRACE("Falling back to ChoosePixelFormat as we weren't able to find an exactly matching pixel format\n");
208         /* PixelFormat selection */
209         ZeroMemory(&pfd, sizeof(pfd));
210         pfd.nSize      = sizeof(pfd);
211         pfd.nVersion   = 1;
212         pfd.dwFlags    = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
213         pfd.iPixelType = PFD_TYPE_RGBA;
214         pfd.cAlphaBits = alphaBits;
215         pfd.cColorBits = colorBits;
216         pfd.cDepthBits = depthBits;
217         pfd.cStencilBits = stencilBits;
218         pfd.iLayerType = PFD_MAIN_PLANE;
219
220         iPixelFormat = ChoosePixelFormat(hdc, &pfd);
221         if(!iPixelFormat) {
222             /* If this happens something is very wrong as ChoosePixelFormat barely fails */
223             ERR("Can't find a suitable iPixelFormat\n");
224             return FALSE;
225         }
226     }
227
228     TRACE("Found iPixelFormat=%d for ColorFormat=%s, DepthStencilFormat=%s\n", iPixelFormat, debug_d3dformat(ColorFormat), debug_d3dformat(DepthStencilFormat));
229     return iPixelFormat;
230 }
231
232 /*****************************************************************************
233  * CreateContext
234  *
235  * Creates a new context for a window, or a pbuffer context.
236  *
237  * * Params:
238  *  This: Device to activate the context for
239  *  target: Surface this context will render to
240  *  win_handle: handle to the window which we are drawing to
241  *  create_pbuffer: tells whether to create a pbuffer or not
242  *  pPresentParameters: contains the pixelformats to use for onscreen rendering
243  *
244  *****************************************************************************/
245 WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, HWND win_handle, BOOL create_pbuffer, const WINED3DPRESENT_PARAMETERS *pPresentParms) {
246     HDC oldDrawable, hdc;
247     HPBUFFERARB pbuffer = NULL;
248     HGLRC ctx = NULL, oldCtx;
249     WineD3DContext *ret = NULL;
250     int s;
251
252     TRACE("(%p): Creating a %s context for render target %p\n", This, create_pbuffer ? "offscreen" : "onscreen", target);
253
254     if(create_pbuffer) {
255         HDC hdc_parent = GetDC(win_handle);
256         int iPixelFormat = 0;
257
258         IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
259         WINED3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
260
261         /* Try to find a pixel format with pbuffer support. */
262         iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc_parent, target->resource.format, StencilBufferFormat, FALSE /* auxBuffers */, 0 /* numSamples */, TRUE /* PBUFFER */, FALSE /* findCompatible */);
263         if(!iPixelFormat) {
264             TRACE("Trying to locate a compatible pixel format because an exact match failed.\n");
265
266             /* For some reason we weren't able to find a format, try to find something instead of crashing.
267              * A reason for failure could have been wglChoosePixelFormatARB strictness. */
268             iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc_parent, target->resource.format, StencilBufferFormat, FALSE /* auxBuffer */, 0 /* numSamples */, TRUE /* PBUFFER */, TRUE /* findCompatible */);
269         }
270
271         /* This shouldn't happen as ChoosePixelFormat always returns something */
272         if(!iPixelFormat) {
273             ERR("Unable to locate a pixel format for a pbuffer\n");
274             ReleaseDC(win_handle, hdc_parent);
275             goto out;
276         }
277
278         TRACE("Creating a pBuffer drawable for the new context\n");
279         pbuffer = GL_EXTCALL(wglCreatePbufferARB(hdc_parent, iPixelFormat, target->currentDesc.Width, target->currentDesc.Height, 0));
280         if(!pbuffer) {
281             ERR("Cannot create a pbuffer\n");
282             ReleaseDC(win_handle, hdc_parent);
283             goto out;
284         }
285
286         /* In WGL a pbuffer is 'wrapped' inside a HDC to 'fool' wglMakeCurrent */
287         hdc = GL_EXTCALL(wglGetPbufferDCARB(pbuffer));
288         if(!hdc) {
289             ERR("Cannot get a HDC for pbuffer (%p)\n", pbuffer);
290             GL_EXTCALL(wglDestroyPbufferARB(pbuffer));
291             ReleaseDC(win_handle, hdc_parent);
292             goto out;
293         }
294         ReleaseDC(win_handle, hdc_parent);
295     } else {
296         PIXELFORMATDESCRIPTOR pfd;
297         int iPixelFormat;
298         int res;
299         WINED3DFORMAT ColorFormat = target->resource.format;
300         WINED3DFORMAT DepthStencilFormat = 0;
301         BOOL auxBuffers = FALSE;
302         int numSamples = 0;
303
304         hdc = GetDC(win_handle);
305         if(hdc == NULL) {
306             ERR("Cannot retrieve a device context!\n");
307             goto out;
308         }
309
310         /* In case of ORM_BACKBUFFER, make sure to request an alpha component for X4R4G4B4/X8R8G8B8 as we might need it for the backbuffer. */
311         if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
312             auxBuffers = TRUE;
313
314             if(target->resource.format == WINED3DFMT_X4R4G4B4)
315                 ColorFormat = WINED3DFMT_A4R4G4B4;
316             else if(target->resource.format == WINED3DFMT_X8R8G8B8)
317                 ColorFormat = WINED3DFMT_A8R8G8B8;
318         }
319
320         /* DirectDraw supports 8bit paletted render targets and these are used by old games like Starcraft and C&C.
321          * Most modern hardware doesn't support 8bit natively so we perform some form of 8bit -> 32bit conversion.
322          * The conversion (ab)uses the alpha component for storing the palette index. For this reason we require
323          * a format with 8bit alpha, so request A8R8G8B8. */
324         if(ColorFormat == WINED3DFMT_P8)
325             ColorFormat = WINED3DFMT_A8R8G8B8;
326
327         /* Retrieve the depth stencil format from the present parameters.
328          * The choice of the proper format can give a nice performance boost
329          * in case of GPU limited programs. */
330         if(pPresentParms->EnableAutoDepthStencil) {
331             TRACE("pPresentParms->EnableAutoDepthStencil=enabled; using AutoDepthStencilFormat=%s\n", debug_d3dformat(pPresentParms->AutoDepthStencilFormat));
332             DepthStencilFormat = pPresentParms->AutoDepthStencilFormat;
333         }
334
335         /* D3D only allows multisampling when SwapEffect is set to WINED3DSWAPEFFECT_DISCARD */
336         if(pPresentParms->MultiSampleType && (pPresentParms->SwapEffect == WINED3DSWAPEFFECT_DISCARD)) {
337             if(!GL_SUPPORT(ARB_MULTISAMPLE))
338                 ERR("The program is requesting multisampling without support!\n");
339             else {
340                 ERR("Requesting MultiSampleType=%d\n", pPresentParms->MultiSampleType);
341                 numSamples = pPresentParms->MultiSampleType;
342             }
343         }
344
345         /* Try to find a pixel format which matches our requirements */
346         iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc, ColorFormat, DepthStencilFormat, auxBuffers, numSamples, FALSE /* PBUFFER */, FALSE /* findCompatible */);
347
348         /* Try to locate a compatible format if we weren't able to find anything */
349         if(!iPixelFormat) {
350             TRACE("Trying to locate a compatible pixel format because an exact match failed.\n");
351             iPixelFormat = WineD3D_ChoosePixelFormat(This, hdc, ColorFormat, DepthStencilFormat, auxBuffers, 0 /* numSamples */, FALSE /* PBUFFER */, TRUE /* findCompatible */ );
352         }
353
354         /* If we still don't have a pixel format, something is very wrong as ChoosePixelFormat barely fails */
355         if(!iPixelFormat) {
356             ERR("Can't find a suitable iPixelFormat\n");
357             return FALSE;
358         }
359
360         DescribePixelFormat(hdc, iPixelFormat, sizeof(pfd), &pfd);
361         res = SetPixelFormat(hdc, iPixelFormat, NULL);
362         if(!res) {
363             int oldPixelFormat = GetPixelFormat(hdc);
364
365             /* By default WGL doesn't allow pixel format adjustments but we need it here.
366              * For this reason there is a WINE-specific wglSetPixelFormat which allows you to
367              * set the pixel format multiple times. Only use it when it is really needed. */
368
369             if(oldPixelFormat == iPixelFormat) {
370                 /* We don't have to do anything as the formats are the same :) */
371             } else if(oldPixelFormat && GL_SUPPORT(WGL_WINE_PIXEL_FORMAT_PASSTHROUGH)) {
372                 res = GL_EXTCALL(wglSetPixelFormatWINE(hdc, iPixelFormat, NULL));
373
374                 if(!res) {
375                     ERR("wglSetPixelFormatWINE failed on HDC=%p for iPixelFormat=%d\n", hdc, iPixelFormat);
376                     return FALSE;
377                 }
378             } else if(oldPixelFormat) {
379                 /* OpenGL doesn't allow pixel format adjustments. Print an error and continue using the old format.
380                  * There's a big chance that the old format works although with a performance hit and perhaps rendering errors. */
381                 ERR("HDC=%p is already set to iPixelFormat=%d and OpenGL doesn't allow changes!\n", hdc, oldPixelFormat);
382             } else {
383                 ERR("SetPixelFormat failed on HDC=%p for iPixelFormat=%d\n", hdc, iPixelFormat);
384                 return FALSE;
385             }
386         }
387     }
388
389     ctx = pwglCreateContext(hdc);
390     if(This->numContexts) pwglShareLists(This->contexts[0]->glCtx, ctx);
391
392     if(!ctx) {
393         ERR("Failed to create a WGL context\n");
394         if(create_pbuffer) {
395             GL_EXTCALL(wglReleasePbufferDCARB(pbuffer, hdc));
396             GL_EXTCALL(wglDestroyPbufferARB(pbuffer));
397         }
398         goto out;
399     }
400     ret = AddContextToArray(This, win_handle, hdc, ctx, pbuffer);
401     if(!ret) {
402         ERR("Failed to add the newly created context to the context list\n");
403         pwglDeleteContext(ctx);
404         if(create_pbuffer) {
405             GL_EXTCALL(wglReleasePbufferDCARB(pbuffer, hdc));
406             GL_EXTCALL(wglDestroyPbufferARB(pbuffer));
407         }
408         goto out;
409     }
410     ret->surface = (IWineD3DSurface *) target;
411     ret->isPBuffer = create_pbuffer;
412     ret->tid = GetCurrentThreadId();
413     if(This->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) This)) {
414         /* Create the dirty constants array and initialize them to dirty */
415         ret->vshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
416                 sizeof(*ret->vshader_const_dirty) * GL_LIMITS(vshader_constantsF));
417         ret->pshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
418                 sizeof(*ret->pshader_const_dirty) * GL_LIMITS(pshader_constantsF));
419         memset(ret->vshader_const_dirty, 1,
420                sizeof(*ret->vshader_const_dirty) * GL_LIMITS(vshader_constantsF));
421         memset(ret->pshader_const_dirty, 1,
422                 sizeof(*ret->pshader_const_dirty) * GL_LIMITS(pshader_constantsF));
423     }
424
425     TRACE("Successfully created new context %p\n", ret);
426
427     /* Set up the context defaults */
428     oldCtx  = pwglGetCurrentContext();
429     oldDrawable = pwglGetCurrentDC();
430     if(oldCtx && oldDrawable) {
431         /* See comment in ActivateContext context switching */
432         This->shader_backend->shader_fragment_enable((IWineD3DDevice *) This, FALSE);
433     }
434     if(pwglMakeCurrent(hdc, ctx) == FALSE) {
435         ERR("Cannot activate context to set up defaults\n");
436         goto out;
437     }
438
439     ENTER_GL();
440
441     glGetIntegerv(GL_AUX_BUFFERS, &ret->aux_buffers);
442
443     TRACE("Setting up the screen\n");
444     /* Clear the screen */
445     glClearColor(1.0, 0.0, 0.0, 0.0);
446     checkGLcall("glClearColor");
447     glClearIndex(0);
448     glClearDepth(1);
449     glClearStencil(0xffff);
450
451     checkGLcall("glClear");
452
453     glColor3f(1.0, 1.0, 1.0);
454     checkGLcall("glColor3f");
455
456     glEnable(GL_LIGHTING);
457     checkGLcall("glEnable");
458
459     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
460     checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
461
462     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
463     checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
464
465     glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
466     checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
467
468     glPixelStorei(GL_PACK_ALIGNMENT, This->surface_alignment);
469     checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, This->surface_alignment);");
470     glPixelStorei(GL_UNPACK_ALIGNMENT, This->surface_alignment);
471     checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, This->surface_alignment);");
472
473     if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
474         /* Most textures will use client storage if supported. Exceptions are non-native power of 2 textures
475          * and textures in DIB sections(due to the memory protection).
476          */
477         glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
478         checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
479     }
480     if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
481         /* Direct3D always uses n-1 weights for n world matrices and uses 1 - sum for the last one
482          * this is equal to GL_WEIGHT_SUM_UNITY_ARB. Enabling it doesn't do anything unless
483          * GL_VERTEX_BLEND_ARB isn't enabled too
484          */
485         glEnable(GL_WEIGHT_SUM_UNITY_ARB);
486         checkGLcall("glEnable(GL_WEIGHT_SUM_UNITY_ARB)");
487     }
488     if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
489         glEnable(GL_TEXTURE_SHADER_NV);
490         checkGLcall("glEnable(GL_TEXTURE_SHADER_NV)");
491
492         /* Set up the previous texture input for all shader units. This applies to bump mapping, and in d3d
493          * the previous texture where to source the offset from is always unit - 1.
494          */
495         for(s = 1; s < GL_LIMITS(textures); s++) {
496             GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + s));
497             glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + s - 1);
498             checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, ...\n");
499         }
500     }
501
502     if(GL_SUPPORT(ARB_POINT_SPRITE)) {
503         for(s = 0; s < GL_LIMITS(textures); s++) {
504             GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + s));
505             glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
506             checkGLcall("glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
507         }
508     }
509     LEAVE_GL();
510
511     /* Never keep GL_FRAGMENT_SHADER_ATI enabled on a context that we switch away from,
512      * but enable it for the first context we create, and reenable it on the old context
513      */
514     if(oldDrawable && oldCtx) {
515         pwglMakeCurrent(oldDrawable, oldCtx);
516     }
517     This->shader_backend->shader_fragment_enable((IWineD3DDevice *) This, TRUE);
518
519 out:
520     return ret;
521 }
522
523 /*****************************************************************************
524  * RemoveContextFromArray
525  *
526  * Removes a context from the context manager. The opengl context is not
527  * destroyed or unset. context is not a valid pointer after that call.
528  *
529  * Similar to the former call this isn't a performance critical function. A
530  * helper function for DestroyContext.
531  *
532  * Params:
533  *  This: Device to activate the context for
534  *  context: Context to remove
535  *
536  *****************************************************************************/
537 static void RemoveContextFromArray(IWineD3DDeviceImpl *This, WineD3DContext *context) {
538     UINT t, s;
539     WineD3DContext **oldArray = This->contexts;
540
541     TRACE("Removing ctx %p\n", context);
542
543     This->numContexts--;
544
545     if(This->numContexts) {
546         This->contexts = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->contexts) * This->numContexts);
547         if(!This->contexts) {
548             ERR("Cannot allocate a new context array, PANIC!!!\n");
549         }
550         t = 0;
551         /* Note that we decreased numContexts a few lines up, so use '<=' instead of '<' */
552         for(s = 0; s <= This->numContexts; s++) {
553             if(oldArray[s] == context) continue;
554             This->contexts[t] = oldArray[s];
555             t++;
556         }
557     } else {
558         This->contexts = NULL;
559     }
560
561     HeapFree(GetProcessHeap(), 0, context);
562     HeapFree(GetProcessHeap(), 0, oldArray);
563 }
564
565 /*****************************************************************************
566  * DestroyContext
567  *
568  * Destroys a wineD3DContext
569  *
570  * Params:
571  *  This: Device to activate the context for
572  *  context: Context to destroy
573  *
574  *****************************************************************************/
575 void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context) {
576
577     /* check that we are the current context first */
578     TRACE("Destroying ctx %p\n", context);
579     if(pwglGetCurrentContext() == context->glCtx){
580         pwglMakeCurrent(NULL, NULL);
581     }
582
583     if(context->isPBuffer) {
584         GL_EXTCALL(wglReleasePbufferDCARB(context->pbuffer, context->hdc));
585         GL_EXTCALL(wglDestroyPbufferARB(context->pbuffer));
586     } else ReleaseDC(context->win_handle, context->hdc);
587     pwglDeleteContext(context->glCtx);
588
589     HeapFree(GetProcessHeap(), 0, context->vshader_const_dirty);
590     HeapFree(GetProcessHeap(), 0, context->pshader_const_dirty);
591     RemoveContextFromArray(This, context);
592 }
593
594 /*****************************************************************************
595  * SetupForBlit
596  *
597  * Sets up a context for DirectDraw blitting.
598  * All texture units are disabled, texture unit 0 is set as current unit
599  * fog, lighting, blending, alpha test, z test, scissor test, culling disabled
600  * color writing enabled for all channels
601  * register combiners disabled, shaders disabled
602  * world matrix is set to identity, texture matrix 0 too
603  * projection matrix is setup for drawing screen coordinates
604  *
605  * Params:
606  *  This: Device to activate the context for
607  *  context: Context to setup
608  *  width: render target width
609  *  height: render target height
610  *
611  *****************************************************************************/
612 static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *context, UINT width, UINT height) {
613     int i;
614     const struct StateEntry *StateTable = This->shader_backend->StateTable;
615
616     TRACE("Setting up context %p for blitting\n", context);
617     if(context->last_was_blit) {
618         TRACE("Context is already set up for blitting, nothing to do\n");
619         return;
620     }
621     context->last_was_blit = TRUE;
622
623     /* TODO: Use a display list */
624
625     /* Disable shaders */
626     This->shader_backend->shader_cleanup((IWineD3DDevice *) This);
627     Context_MarkStateDirty(context, STATE_VSHADER, StateTable);
628     Context_MarkStateDirty(context, STATE_PIXELSHADER, StateTable);
629
630     /* Disable all textures. The caller can then bind a texture it wants to blit
631      * from
632      */
633     if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
634         glDisable(GL_REGISTER_COMBINERS_NV);
635         checkGLcall("glDisable(GL_REGISTER_COMBINERS_NV)");
636     }
637     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
638         /* The blitting code uses (for now) the fixed function pipeline, so make sure to reset all fixed
639          * function texture unit. No need to care for higher samplers
640          */
641         for(i = GL_LIMITS(textures) - 1; i > 0 ; i--) {
642             GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
643             checkGLcall("glActiveTextureARB");
644
645             if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
646                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
647                 checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
648             }
649             glDisable(GL_TEXTURE_3D);
650             checkGLcall("glDisable GL_TEXTURE_3D");
651             glDisable(GL_TEXTURE_2D);
652             checkGLcall("glDisable GL_TEXTURE_2D");
653
654             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
655             checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);");
656
657             Context_MarkStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), StateTable);
658             Context_MarkStateDirty(context, STATE_SAMPLER(i), StateTable);
659         }
660         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
661         checkGLcall("glActiveTextureARB");
662     }
663     if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
664         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
665         checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
666     }
667     glDisable(GL_TEXTURE_3D);
668     checkGLcall("glDisable GL_TEXTURE_3D");
669     glDisable(GL_TEXTURE_2D);
670     checkGLcall("glDisable GL_TEXTURE_2D");
671
672     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
673
674     glMatrixMode(GL_TEXTURE);
675     checkGLcall("glMatrixMode(GL_TEXTURE)");
676     glLoadIdentity();
677     checkGLcall("glLoadIdentity()");
678     Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0), StateTable);
679
680     if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
681         glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
682                   GL_TEXTURE_LOD_BIAS_EXT,
683                   0.0);
684         checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
685     }
686     Context_MarkStateDirty(context, STATE_SAMPLER(0), StateTable);
687     Context_MarkStateDirty(context, STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), StateTable);
688
689     /* Other misc states */
690     glDisable(GL_ALPHA_TEST);
691     checkGLcall("glDisable(GL_ALPHA_TEST)");
692     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHATESTENABLE), StateTable);
693     glDisable(GL_LIGHTING);
694     checkGLcall("glDisable GL_LIGHTING");
695     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING), StateTable);
696     glDisable(GL_DEPTH_TEST);
697     checkGLcall("glDisable GL_DEPTH_TEST");
698     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ZENABLE), StateTable);
699     glDisable(GL_FOG);
700     checkGLcall("glDisable GL_FOG");
701     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_FOGENABLE), StateTable);
702     glDisable(GL_BLEND);
703     checkGLcall("glDisable GL_BLEND");
704     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
705     glDisable(GL_CULL_FACE);
706     checkGLcall("glDisable GL_CULL_FACE");
707     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_CULLMODE), StateTable);
708     glDisable(GL_STENCIL_TEST);
709     checkGLcall("glDisable GL_STENCIL_TEST");
710     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_STENCILENABLE), StateTable);
711     glDisable(GL_SCISSOR_TEST);
712     checkGLcall("glDisable GL_SCISSOR_TEST");
713     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), StateTable);
714     if(GL_SUPPORT(ARB_POINT_SPRITE)) {
715         glDisable(GL_POINT_SPRITE_ARB);
716         checkGLcall("glDisable GL_POINT_SPRITE_ARB");
717         Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), StateTable);
718     }
719     glColorMask(GL_TRUE, GL_TRUE,GL_TRUE,GL_TRUE);
720     checkGLcall("glColorMask");
721     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPING), StateTable);
722     if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
723         glDisable(GL_COLOR_SUM_EXT);
724         Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SPECULARENABLE), StateTable);
725         checkGLcall("glDisable(GL_COLOR_SUM_EXT)");
726     }
727     if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
728         GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
729         Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SPECULARENABLE), StateTable);
730         checkGLcall("glFinalCombinerInputNV");
731     }
732
733     /* Setup transforms */
734     glMatrixMode(GL_MODELVIEW);
735     checkGLcall("glMatrixMode(GL_MODELVIEW)");
736     glLoadIdentity();
737     checkGLcall("glLoadIdentity()");
738     Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), StateTable);
739
740     glMatrixMode(GL_PROJECTION);
741     checkGLcall("glMatrixMode(GL_PROJECTION)");
742     glLoadIdentity();
743     checkGLcall("glLoadIdentity()");
744     glOrtho(0, width, height, 0, 0.0, -1.0);
745     checkGLcall("glOrtho");
746     Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION), StateTable);
747
748     context->last_was_rhw = TRUE;
749     Context_MarkStateDirty(context, STATE_VDECL, StateTable); /* because of last_was_rhw = TRUE */
750
751     glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)");
752     glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)");
753     glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)");
754     glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)");
755     glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)");
756     glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)");
757     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPING), StateTable);
758
759     glViewport(0, 0, width, height);
760     checkGLcall("glViewport");
761     Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable);
762
763     This->shader_backend->shader_fragment_enable((IWineD3DDevice *) This, FALSE);
764 }
765
766 /*****************************************************************************
767  * findThreadContextForSwapChain
768  *
769  * Searches a swapchain for all contexts and picks one for the thread tid.
770  * If none can be found the swapchain is requested to create a new context
771  *
772  *****************************************************************************/
773 static WineD3DContext *findThreadContextForSwapChain(IWineD3DSwapChain *swapchain, DWORD tid) {
774     int i;
775
776     for(i = 0; i < ((IWineD3DSwapChainImpl *) swapchain)->num_contexts; i++) {
777         if(((IWineD3DSwapChainImpl *) swapchain)->context[i]->tid == tid) {
778             return ((IWineD3DSwapChainImpl *) swapchain)->context[i];
779         }
780
781     }
782
783     /* Create a new context for the thread */
784     return IWineD3DSwapChainImpl_CreateContextForThread(swapchain);
785 }
786
787 /*****************************************************************************
788  * FindContext
789  *
790  * Finds a context for the current render target and thread
791  *
792  * Parameters:
793  *  target: Render target to find the context for
794  *  tid: Thread to activate the context for
795  *
796  * Returns: The needed context
797  *
798  *****************************************************************************/
799 static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, DWORD tid, GLint *buffer) {
800     IWineD3DSwapChain *swapchain = NULL;
801     HRESULT hr;
802     BOOL readTexture = wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->render_offscreen;
803     WineD3DContext *context = This->activeContext;
804     BOOL oldRenderOffscreen = This->render_offscreen;
805     const WINED3DFORMAT oldFmt = ((IWineD3DSurfaceImpl *) This->lastActiveRenderTarget)->resource.format;
806     const WINED3DFORMAT newFmt = ((IWineD3DSurfaceImpl *) target)->resource.format;
807     const struct StateEntry *StateTable = This->shader_backend->StateTable;
808
809     /* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers
810      * the alpha blend state changes with different render target formats
811      */
812     if(oldFmt != newFmt) {
813         const GlPixelFormatDesc *glDesc;
814         const StaticPixelFormatDesc *old = getFormatDescEntry(oldFmt, NULL, NULL);
815         const StaticPixelFormatDesc *new = getFormatDescEntry(newFmt, &GLINFO_LOCATION, &glDesc);
816
817         /* Disable blending when the alphaMask has changed and when a format doesn't support blending */
818         if((old->alphaMask && !new->alphaMask) || (!old->alphaMask && new->alphaMask) || !(glDesc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)) {
819             Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
820         }
821     }
822
823     hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **) &swapchain);
824     if(hr == WINED3D_OK && swapchain) {
825         TRACE("Rendering onscreen\n");
826
827         context = findThreadContextForSwapChain(swapchain, tid);
828
829         This->render_offscreen = FALSE;
830         /* The context != This->activeContext will catch a NOP context change. This can occur
831          * if we are switching back to swapchain rendering in case of FBO or Back Buffer offscreen
832          * rendering. No context change is needed in that case
833          */
834
835         if(((IWineD3DSwapChainImpl *) swapchain)->frontBuffer == target) {
836             *buffer = GL_FRONT;
837         } else {
838             *buffer = GL_BACK;
839         }
840         if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
841             if(This->pbufferContext && tid == This->pbufferContext->tid) {
842                 This->pbufferContext->tid = 0;
843             }
844         }
845         IWineD3DSwapChain_Release(swapchain);
846
847         if(oldRenderOffscreen) {
848             Context_MarkStateDirty(context, WINED3DTS_PROJECTION, StateTable);
849             Context_MarkStateDirty(context, STATE_VDECL, StateTable);
850             Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable);
851             Context_MarkStateDirty(context, STATE_SCISSORRECT, StateTable);
852             Context_MarkStateDirty(context, STATE_FRONTFACE, StateTable);
853         }
854
855     } else {
856         TRACE("Rendering offscreen\n");
857         This->render_offscreen = TRUE;
858         *buffer = This->offscreenBuffer;
859
860         switch(wined3d_settings.offscreen_rendering_mode) {
861             case ORM_FBO:
862                 /* FBOs do not need a different context. Stay with whatever context is active at the moment */
863                 if(This->activeContext && tid == This->lastThread) {
864                     context = This->activeContext;
865                 } else {
866                     /* This may happen if the app jumps straight into offscreen rendering
867                      * Start using the context of the primary swapchain. tid == 0 is no problem
868                      * for findThreadContextForSwapChain.
869                      *
870                      * Can also happen on thread switches - in that case findThreadContextForSwapChain
871                      * is perfect to call.
872                      */
873                     context = findThreadContextForSwapChain(This->swapchains[0], tid);
874                 }
875                 break;
876
877             case ORM_PBUFFER:
878             {
879                 IWineD3DSurfaceImpl *targetimpl = (IWineD3DSurfaceImpl *) target;
880                 if(This->pbufferContext == NULL ||
881                    This->pbufferWidth < targetimpl->currentDesc.Width ||
882                    This->pbufferHeight < targetimpl->currentDesc.Height) {
883                     if(This->pbufferContext) {
884                         DestroyContext(This, This->pbufferContext);
885                     }
886
887                     /* The display is irrelevant here, the window is 0. But CreateContext needs a valid X connection.
888                      * Create the context on the same server as the primary swapchain. The primary swapchain is exists at this point.
889                      */
890                     This->pbufferContext = CreateContext(This, targetimpl,
891                             ((IWineD3DSwapChainImpl *) This->swapchains[0])->context[0]->win_handle,
892                             TRUE /* pbuffer */, &((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms);
893                     This->pbufferWidth = targetimpl->currentDesc.Width;
894                     This->pbufferHeight = targetimpl->currentDesc.Height;
895                    }
896
897                    if(This->pbufferContext) {
898                        if(This->pbufferContext->tid != 0 && This->pbufferContext->tid != tid) {
899                            FIXME("The PBuffr context is only supported for one thread for now!\n");
900                        }
901                        This->pbufferContext->tid = tid;
902                        context = This->pbufferContext;
903                        break;
904                    } else {
905                        ERR("Failed to create a buffer context and drawable, falling back to back buffer offscreen rendering\n");
906                        wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
907                    }
908             }
909
910             case ORM_BACKBUFFER:
911                 /* Stay with the currently active context for back buffer rendering */
912                 if(This->activeContext && tid == This->lastThread) {
913                     context = This->activeContext;
914                 } else {
915                     /* This may happen if the app jumps straight into offscreen rendering
916                      * Start using the context of the primary swapchain. tid == 0 is no problem
917                      * for findThreadContextForSwapChain.
918                      *
919                      * Can also happen on thread switches - in that case findThreadContextForSwapChain
920                      * is perfect to call.
921                      */
922                     context = findThreadContextForSwapChain(This->swapchains[0], tid);
923                 }
924                 break;
925         }
926
927         if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
928             /* Make sure we have a OpenGL texture name so the PreLoad() used to read the buffer
929              * back when we are done won't mark us dirty.
930              */
931             IWineD3DSurface_PreLoad(target);
932         }
933
934         if(!oldRenderOffscreen) {
935             Context_MarkStateDirty(context, WINED3DTS_PROJECTION, StateTable);
936             Context_MarkStateDirty(context, STATE_VDECL, StateTable);
937             Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable);
938             Context_MarkStateDirty(context, STATE_SCISSORRECT, StateTable);
939             Context_MarkStateDirty(context, STATE_FRONTFACE, StateTable);
940         }
941     }
942     if (readTexture) {
943         BOOL oldInDraw = This->isInDraw;
944
945         /* PreLoad requires a context to load the texture, thus it will call ActivateContext.
946          * Set the isInDraw to true to signal PreLoad that it has a context. Will be tricky
947          * when using offscreen rendering with multithreading
948          */
949         This->isInDraw = TRUE;
950
951         /* Do that before switching the context:
952          * Read the back buffer of the old drawable into the destination texture
953          */
954         IWineD3DSurface_PreLoad(This->lastActiveRenderTarget);
955
956         /* Assume that the drawable will be modified by some other things now */
957         IWineD3DSurface_ModifyLocation(This->lastActiveRenderTarget, SFLAG_INDRAWABLE, FALSE);
958
959         This->isInDraw = oldInDraw;
960     }
961
962     if(oldRenderOffscreen != This->render_offscreen && This->depth_copy_state != WINED3D_DCS_NO_COPY) {
963         This->depth_copy_state = WINED3D_DCS_COPY;
964     }
965     return context;
966 }
967
968 /*****************************************************************************
969  * ActivateContext
970  *
971  * Finds a rendering context and drawable matching the device and render
972  * target for the current thread, activates them and puts them into the
973  * requested state.
974  *
975  * Params:
976  *  This: Device to activate the context for
977  *  target: Requested render target
978  *  usage: Prepares the context for blitting, drawing or other actions
979  *
980  *****************************************************************************/
981 void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextUsage usage) {
982     DWORD                         tid = GetCurrentThreadId();
983     int                           i;
984     DWORD                         dirtyState, idx;
985     BYTE                          shift;
986     WineD3DContext                *context;
987     GLint                         drawBuffer=0;
988     const struct StateEntry       *StateTable = This->shader_backend->StateTable;
989
990     TRACE("(%p): Selecting context for render target %p, thread %d\n", This, target, tid);
991     if(This->lastActiveRenderTarget != target || tid != This->lastThread) {
992         context = FindContext(This, target, tid, &drawBuffer);
993         This->lastActiveRenderTarget = target;
994         This->lastThread = tid;
995     } else {
996         /* Stick to the old context */
997         context = This->activeContext;
998     }
999
1000     /* Activate the opengl context */
1001     if(context != This->activeContext) {
1002         BOOL ret;
1003
1004         /* Prevent an unneeded context switch as those are expensive */
1005         if(context->glCtx && (context->glCtx == pwglGetCurrentContext())) {
1006             TRACE("Already using gl context %p\n", context->glCtx);
1007         }
1008         else {
1009             TRACE("Switching gl ctx to %p, hdc=%p ctx=%p\n", context, context->hdc, context->glCtx);
1010
1011             This->shader_backend->shader_fragment_enable((IWineD3DDevice *) This, FALSE);
1012             ret = pwglMakeCurrent(context->hdc, context->glCtx);
1013             if(ret == FALSE) {
1014                 ERR("Failed to activate the new context\n");
1015             } else if(!context->last_was_blit) {
1016                 This->shader_backend->shader_fragment_enable((IWineD3DDevice *) This, TRUE);
1017             }
1018         }
1019         if(This->activeContext->vshader_const_dirty) {
1020             memset(This->activeContext->vshader_const_dirty, 1,
1021                    sizeof(*This->activeContext->vshader_const_dirty) * GL_LIMITS(vshader_constantsF));
1022         }
1023         if(This->activeContext->pshader_const_dirty) {
1024             memset(This->activeContext->pshader_const_dirty, 1,
1025                    sizeof(*This->activeContext->pshader_const_dirty) * GL_LIMITS(pshader_constantsF));
1026         }
1027         This->activeContext = context;
1028     }
1029
1030     /* We only need ENTER_GL for the gl calls made below and for the helper functions which make GL calls */
1031     ENTER_GL();
1032     /* Select the right draw buffer. It is selected in FindContext. */
1033     if(drawBuffer && context->last_draw_buffer != drawBuffer) {
1034         TRACE("Drawing to buffer: %#x\n", drawBuffer);
1035         context->last_draw_buffer = drawBuffer;
1036
1037         glDrawBuffer(drawBuffer);
1038         checkGLcall("glDrawBuffer");
1039     }
1040
1041     switch(usage) {
1042         case CTXUSAGE_RESOURCELOAD:
1043             /* This does not require any special states to be set up */
1044             break;
1045
1046         case CTXUSAGE_CLEAR:
1047             if(context->last_was_blit) {
1048                 This->shader_backend->shader_fragment_enable((IWineD3DDevice *) This, TRUE);
1049             }
1050
1051             /* Blending and clearing should be orthogonal, but tests on the nvidia driver show that disabling
1052              * blending when clearing improves the clearing performance incredibly.
1053              */
1054             glDisable(GL_BLEND);
1055             Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
1056
1057             glEnable(GL_SCISSOR_TEST);
1058             checkGLcall("glEnable GL_SCISSOR_TEST");
1059             context->last_was_blit = FALSE;
1060             Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), StateTable);
1061             Context_MarkStateDirty(context, STATE_SCISSORRECT, StateTable);
1062             break;
1063
1064         case CTXUSAGE_DRAWPRIM:
1065             /* This needs all dirty states applied */
1066             if(context->last_was_blit) {
1067                 This->shader_backend->shader_fragment_enable((IWineD3DDevice *) This, TRUE);
1068             }
1069
1070             IWineD3DDeviceImpl_FindTexUnitMap(This);
1071
1072             for(i=0; i < context->numDirtyEntries; i++) {
1073                 dirtyState = context->dirtyArray[i];
1074                 idx = dirtyState >> 5;
1075                 shift = dirtyState & 0x1f;
1076                 context->isStateDirty[idx] &= ~(1 << shift);
1077                 StateTable[dirtyState].apply(dirtyState, This->stateBlock, context);
1078             }
1079             context->numDirtyEntries = 0; /* This makes the whole list clean */
1080             context->last_was_blit = FALSE;
1081             break;
1082
1083         case CTXUSAGE_BLIT:
1084             SetupForBlit(This, context,
1085                          ((IWineD3DSurfaceImpl *)target)->currentDesc.Width,
1086                          ((IWineD3DSurfaceImpl *)target)->currentDesc.Height);
1087             break;
1088
1089         default:
1090             FIXME("Unexpected context usage requested\n");
1091     }
1092     LEAVE_GL();
1093 }