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