twain_32: Mark some functions static and other internal ones hidden.
[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  * Copyright 2009-2011 Henri Verbeet for CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include <stdio.h>
24 #ifdef HAVE_FLOAT_H
25 # include <float.h>
26 #endif
27 #include "wined3d_private.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
30
31 static DWORD wined3d_context_tls_idx;
32
33 /* FBO helper functions */
34
35 /* GL locking is done by the caller */
36 void context_bind_fbo(struct wined3d_context *context, GLenum target, GLuint *fbo)
37 {
38     const struct wined3d_gl_info *gl_info = context->gl_info;
39     GLuint f;
40
41     if (!fbo)
42     {
43         f = 0;
44     }
45     else
46     {
47         if (!*fbo)
48         {
49             gl_info->fbo_ops.glGenFramebuffers(1, fbo);
50             checkGLcall("glGenFramebuffers()");
51             TRACE("Created FBO %u.\n", *fbo);
52         }
53         f = *fbo;
54     }
55
56     switch (target)
57     {
58         case GL_READ_FRAMEBUFFER:
59             if (context->fbo_read_binding == f) return;
60             context->fbo_read_binding = f;
61             break;
62
63         case GL_DRAW_FRAMEBUFFER:
64             if (context->fbo_draw_binding == f) return;
65             context->fbo_draw_binding = f;
66             break;
67
68         case GL_FRAMEBUFFER:
69             if (context->fbo_read_binding == f
70                     && context->fbo_draw_binding == f) return;
71             context->fbo_read_binding = f;
72             context->fbo_draw_binding = f;
73             break;
74
75         default:
76             FIXME("Unhandled target %#x.\n", target);
77             break;
78     }
79
80     gl_info->fbo_ops.glBindFramebuffer(target, f);
81     checkGLcall("glBindFramebuffer()");
82 }
83
84 /* GL locking is done by the caller */
85 static void context_clean_fbo_attachments(const struct wined3d_gl_info *gl_info, GLenum target)
86 {
87     unsigned int i;
88
89     for (i = 0; i < gl_info->limits.buffers; ++i)
90     {
91         gl_info->fbo_ops.glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, 0, 0);
92         checkGLcall("glFramebufferTexture2D()");
93     }
94     gl_info->fbo_ops.glFramebufferTexture2D(target, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
95     checkGLcall("glFramebufferTexture2D()");
96
97     gl_info->fbo_ops.glFramebufferTexture2D(target, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
98     checkGLcall("glFramebufferTexture2D()");
99 }
100
101 /* GL locking is done by the caller */
102 static void context_destroy_fbo(struct wined3d_context *context, GLuint *fbo)
103 {
104     const struct wined3d_gl_info *gl_info = context->gl_info;
105
106     context_bind_fbo(context, GL_FRAMEBUFFER, fbo);
107     context_clean_fbo_attachments(gl_info, GL_FRAMEBUFFER);
108     context_bind_fbo(context, GL_FRAMEBUFFER, NULL);
109
110     gl_info->fbo_ops.glDeleteFramebuffers(1, fbo);
111     checkGLcall("glDeleteFramebuffers()");
112 }
113
114 /* GL locking is done by the caller */
115 static void context_apply_attachment_filter_states(const struct wined3d_context *context,
116         IWineD3DSurfaceImpl *surface, DWORD location)
117 {
118     /* Update base texture states array */
119     if (surface->container.type == WINED3D_CONTAINER_TEXTURE)
120     {
121         struct wined3d_texture *texture = surface->container.u.texture;
122         IWineD3DDeviceImpl *device = surface->resource.device;
123         BOOL update_minfilter = FALSE;
124         BOOL update_magfilter = FALSE;
125         struct gl_texture *gl_tex;
126
127         switch (location)
128         {
129             case SFLAG_INTEXTURE:
130             case SFLAG_INSRGBTEX:
131                 gl_tex = wined3d_texture_get_gl_texture(texture,
132                         context->gl_info, location == SFLAG_INSRGBTEX);
133                 break;
134
135             default:
136                 ERR("Unsupported location %s (%#x).\n", debug_surflocation(location), location);
137                 return;
138         }
139
140         if (gl_tex->states[WINED3DTEXSTA_MINFILTER] != WINED3DTEXF_POINT
141             || gl_tex->states[WINED3DTEXSTA_MIPFILTER] != WINED3DTEXF_NONE)
142         {
143             gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
144             gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3DTEXF_NONE;
145             update_minfilter = TRUE;
146         }
147
148         if (gl_tex->states[WINED3DTEXSTA_MAGFILTER] != WINED3DTEXF_POINT)
149         {
150             gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
151             update_magfilter = TRUE;
152         }
153
154         if (texture->bind_count)
155         {
156             WARN("Render targets should not be bound to a sampler\n");
157             IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SAMPLER(texture->sampler));
158         }
159
160         if (update_minfilter || update_magfilter)
161         {
162             GLenum target, bind_target;
163             GLint old_binding;
164
165             target = surface->texture_target;
166             if (target == GL_TEXTURE_2D)
167             {
168                 bind_target = GL_TEXTURE_2D;
169                 glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
170             }
171             else if (target == GL_TEXTURE_RECTANGLE_ARB)
172             {
173                 bind_target = GL_TEXTURE_RECTANGLE_ARB;
174                 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding);
175             }
176             else
177             {
178                 bind_target = GL_TEXTURE_CUBE_MAP_ARB;
179                 glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
180             }
181
182             glBindTexture(bind_target, gl_tex->name);
183             if (update_minfilter) glTexParameteri(bind_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
184             if (update_magfilter) glTexParameteri(bind_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
185             glBindTexture(bind_target, old_binding);
186         }
187
188         checkGLcall("apply_attachment_filter_states()");
189     }
190 }
191
192 /* GL locking is done by the caller */
193 void context_attach_depth_stencil_fbo(struct wined3d_context *context,
194         GLenum fbo_target, IWineD3DSurfaceImpl *depth_stencil, BOOL use_render_buffer)
195 {
196     const struct wined3d_gl_info *gl_info = context->gl_info;
197
198     TRACE("Attach depth stencil %p\n", depth_stencil);
199
200     if (depth_stencil)
201     {
202         DWORD format_flags = depth_stencil->resource.format->flags;
203
204         if (use_render_buffer && depth_stencil->current_renderbuffer)
205         {
206             if (format_flags & WINED3DFMT_FLAG_DEPTH)
207             {
208                 gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_DEPTH_ATTACHMENT,
209                         GL_RENDERBUFFER, depth_stencil->current_renderbuffer->id);
210                 checkGLcall("glFramebufferRenderbuffer()");
211             }
212
213             if (format_flags & WINED3DFMT_FLAG_STENCIL)
214             {
215                 gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_STENCIL_ATTACHMENT,
216                         GL_RENDERBUFFER, depth_stencil->current_renderbuffer->id);
217                 checkGLcall("glFramebufferRenderbuffer()");
218             }
219         }
220         else
221         {
222             surface_prepare_texture(depth_stencil, gl_info, FALSE);
223             context_apply_attachment_filter_states(context, depth_stencil, SFLAG_INTEXTURE);
224
225             if (format_flags & WINED3DFMT_FLAG_DEPTH)
226             {
227                 gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT,
228                         depth_stencil->texture_target, depth_stencil->texture_name,
229                         depth_stencil->texture_level);
230                 checkGLcall("glFramebufferTexture2D()");
231             }
232
233             if (format_flags & WINED3DFMT_FLAG_STENCIL)
234             {
235                 gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_STENCIL_ATTACHMENT,
236                         depth_stencil->texture_target, depth_stencil->texture_name,
237                         depth_stencil->texture_level);
238                 checkGLcall("glFramebufferTexture2D()");
239             }
240         }
241
242         if (!(format_flags & WINED3DFMT_FLAG_DEPTH))
243         {
244             gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
245             checkGLcall("glFramebufferTexture2D()");
246         }
247
248         if (!(format_flags & WINED3DFMT_FLAG_STENCIL))
249         {
250             gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
251             checkGLcall("glFramebufferTexture2D()");
252         }
253     }
254     else
255     {
256         gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
257         checkGLcall("glFramebufferTexture2D()");
258
259         gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
260         checkGLcall("glFramebufferTexture2D()");
261     }
262 }
263
264 /* GL locking is done by the caller */
265 static void context_attach_surface_fbo(const struct wined3d_context *context,
266         GLenum fbo_target, DWORD idx, IWineD3DSurfaceImpl *surface, DWORD location)
267 {
268     const struct wined3d_gl_info *gl_info = context->gl_info;
269
270     TRACE("Attach surface %p to %u\n", surface, idx);
271
272     if (surface && surface->resource.format->id != WINED3DFMT_NULL)
273     {
274         BOOL srgb;
275
276         switch (location)
277         {
278             case SFLAG_INTEXTURE:
279             case SFLAG_INSRGBTEX:
280                 srgb = location == SFLAG_INSRGBTEX;
281                 surface_prepare_texture(surface, gl_info, srgb);
282                 context_apply_attachment_filter_states(context, surface, location);
283                 gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
284                         surface->texture_target, surface_get_texture_name(surface, gl_info, srgb),
285                         surface->texture_level);
286                 break;
287
288             default:
289                 ERR("Unsupported location %s (%#x).\n", debug_surflocation(location), location);
290                 break;
291         }
292         checkGLcall("glFramebufferTexture2D()");
293     }
294     else
295     {
296         gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx, GL_TEXTURE_2D, 0, 0);
297         checkGLcall("glFramebufferTexture2D()");
298     }
299 }
300
301 /* GL locking is done by the caller */
302 void context_check_fbo_status(struct wined3d_context *context, GLenum target)
303 {
304     const struct wined3d_gl_info *gl_info = context->gl_info;
305     GLenum status;
306
307     status = gl_info->fbo_ops.glCheckFramebufferStatus(target);
308     if (status == GL_FRAMEBUFFER_COMPLETE)
309     {
310         TRACE("FBO complete\n");
311     } else {
312         IWineD3DSurfaceImpl *attachment;
313         unsigned int i;
314         FIXME("FBO status %s (%#x)\n", debug_fbostatus(status), status);
315
316         if (!context->current_fbo)
317         {
318             ERR("FBO 0 is incomplete, driver bug?\n");
319             return;
320         }
321
322         FIXME("\tLocation %s (%#x).\n", debug_surflocation(context->current_fbo->location),
323                 context->current_fbo->location);
324
325         /* Dump the FBO attachments */
326         for (i = 0; i < gl_info->limits.buffers; ++i)
327         {
328             attachment = context->current_fbo->render_targets[i];
329             if (attachment)
330             {
331                 FIXME("\tColor attachment %d: (%p) %s %ux%u\n",
332                         i, attachment, debug_d3dformat(attachment->resource.format->id),
333                         attachment->pow2Width, attachment->pow2Height);
334             }
335         }
336         attachment = context->current_fbo->depth_stencil;
337         if (attachment)
338         {
339             FIXME("\tDepth attachment: (%p) %s %ux%u\n",
340                     attachment, debug_d3dformat(attachment->resource.format->id),
341                     attachment->pow2Width, attachment->pow2Height);
342         }
343     }
344 }
345
346 static struct fbo_entry *context_create_fbo_entry(struct wined3d_context *context,
347         IWineD3DSurfaceImpl **render_targets, IWineD3DSurfaceImpl *depth_stencil, DWORD location)
348 {
349     const struct wined3d_gl_info *gl_info = context->gl_info;
350     struct fbo_entry *entry;
351
352     entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
353     entry->render_targets = HeapAlloc(GetProcessHeap(), 0, gl_info->limits.buffers * sizeof(*entry->render_targets));
354     memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets));
355     entry->depth_stencil = depth_stencil;
356     entry->location = location;
357     entry->attached = FALSE;
358     entry->id = 0;
359
360     return entry;
361 }
362
363 /* GL locking is done by the caller */
364 static void context_reuse_fbo_entry(struct wined3d_context *context, GLenum target,
365         IWineD3DSurfaceImpl **render_targets, IWineD3DSurfaceImpl *depth_stencil,
366         DWORD location, struct fbo_entry *entry)
367 {
368     const struct wined3d_gl_info *gl_info = context->gl_info;
369
370     context_bind_fbo(context, target, &entry->id);
371     context_clean_fbo_attachments(gl_info, target);
372
373     memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets));
374     entry->depth_stencil = depth_stencil;
375     entry->location = location;
376     entry->attached = FALSE;
377 }
378
379 /* GL locking is done by the caller */
380 static void context_destroy_fbo_entry(struct wined3d_context *context, struct fbo_entry *entry)
381 {
382     if (entry->id)
383     {
384         TRACE("Destroy FBO %d\n", entry->id);
385         context_destroy_fbo(context, &entry->id);
386     }
387     --context->fbo_entry_count;
388     list_remove(&entry->entry);
389     HeapFree(GetProcessHeap(), 0, entry->render_targets);
390     HeapFree(GetProcessHeap(), 0, entry);
391 }
392
393
394 /* GL locking is done by the caller */
395 static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context, GLenum target,
396         IWineD3DSurfaceImpl **render_targets, IWineD3DSurfaceImpl *depth_stencil, DWORD location)
397 {
398     const struct wined3d_gl_info *gl_info = context->gl_info;
399     struct fbo_entry *entry;
400
401     if (depth_stencil && render_targets && render_targets[0])
402     {
403         if (depth_stencil->resource.width < render_targets[0]->resource.width ||
404             depth_stencil->resource.height < render_targets[0]->resource.height)
405         {
406             WARN("Depth stencil is smaller than the primary color buffer, disabling\n");
407             depth_stencil = NULL;
408         }
409     }
410
411     LIST_FOR_EACH_ENTRY(entry, &context->fbo_list, struct fbo_entry, entry)
412     {
413         if (!memcmp(entry->render_targets,
414                 render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets))
415                 && entry->depth_stencil == depth_stencil && entry->location == location)
416         {
417             list_remove(&entry->entry);
418             list_add_head(&context->fbo_list, &entry->entry);
419             return entry;
420         }
421     }
422
423     if (context->fbo_entry_count < WINED3D_MAX_FBO_ENTRIES)
424     {
425         entry = context_create_fbo_entry(context, render_targets, depth_stencil, location);
426         list_add_head(&context->fbo_list, &entry->entry);
427         ++context->fbo_entry_count;
428     }
429     else
430     {
431         entry = LIST_ENTRY(list_tail(&context->fbo_list), struct fbo_entry, entry);
432         context_reuse_fbo_entry(context, target, render_targets, depth_stencil, location, entry);
433         list_remove(&entry->entry);
434         list_add_head(&context->fbo_list, &entry->entry);
435     }
436
437     return entry;
438 }
439
440 /* GL locking is done by the caller */
441 static void context_apply_fbo_entry(struct wined3d_context *context, GLenum target, struct fbo_entry *entry)
442 {
443     const struct wined3d_gl_info *gl_info = context->gl_info;
444     unsigned int i;
445
446     context_bind_fbo(context, target, &entry->id);
447
448     if (!entry->attached)
449     {
450         /* Apply render targets */
451         for (i = 0; i < gl_info->limits.buffers; ++i)
452         {
453             context_attach_surface_fbo(context, target, i, entry->render_targets[i], entry->location);
454         }
455
456         /* Apply depth targets */
457         if (entry->depth_stencil)
458             surface_set_compatible_renderbuffer(entry->depth_stencil, entry->render_targets[0]);
459         context_attach_depth_stencil_fbo(context, target, entry->depth_stencil, TRUE);
460
461         entry->attached = TRUE;
462     }
463     else
464     {
465         for (i = 0; i < gl_info->limits.buffers; ++i)
466         {
467             if (entry->render_targets[i])
468                 context_apply_attachment_filter_states(context, entry->render_targets[i], entry->location);
469         }
470         if (entry->depth_stencil)
471             context_apply_attachment_filter_states(context, entry->depth_stencil, SFLAG_INTEXTURE);
472     }
473 }
474
475 /* GL locking is done by the caller */
476 static void context_apply_fbo_state(struct wined3d_context *context, GLenum target,
477         IWineD3DSurfaceImpl **render_targets, IWineD3DSurfaceImpl *depth_stencil, DWORD location)
478 {
479     struct fbo_entry *entry, *entry2;
480
481     LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_destroy_list, struct fbo_entry, entry)
482     {
483         context_destroy_fbo_entry(context, entry);
484     }
485
486     if (context->rebind_fbo)
487     {
488         context_bind_fbo(context, GL_FRAMEBUFFER, NULL);
489         context->rebind_fbo = FALSE;
490     }
491
492     if (render_targets)
493     {
494         context->current_fbo = context_find_fbo_entry(context, target, render_targets, depth_stencil, location);
495         context_apply_fbo_entry(context, target, context->current_fbo);
496     }
497     else
498     {
499         context->current_fbo = NULL;
500         context_bind_fbo(context, target, NULL);
501     }
502 }
503
504 /* GL locking is done by the caller */
505 void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target,
506         IWineD3DSurfaceImpl *render_target, IWineD3DSurfaceImpl *depth_stencil, DWORD location)
507 {
508     if (location != SFLAG_INDRAWABLE || surface_is_offscreen(render_target))
509     {
510         UINT clear_size = (context->gl_info->limits.buffers - 1) * sizeof(*context->blit_targets);
511         context->blit_targets[0] = render_target;
512         if (clear_size) memset(&context->blit_targets[1], 0, clear_size);
513         context_apply_fbo_state(context, target, context->blit_targets, depth_stencil, location);
514     }
515     else
516     {
517         context_apply_fbo_state(context, target, NULL, NULL, location);
518     }
519 }
520
521 /* Context activation is done by the caller. */
522 void context_alloc_occlusion_query(struct wined3d_context *context, struct wined3d_occlusion_query *query)
523 {
524     const struct wined3d_gl_info *gl_info = context->gl_info;
525
526     if (context->free_occlusion_query_count)
527     {
528         query->id = context->free_occlusion_queries[--context->free_occlusion_query_count];
529     }
530     else
531     {
532         if (gl_info->supported[ARB_OCCLUSION_QUERY])
533         {
534             ENTER_GL();
535             GL_EXTCALL(glGenQueriesARB(1, &query->id));
536             checkGLcall("glGenQueriesARB");
537             LEAVE_GL();
538
539             TRACE("Allocated occlusion query %u in context %p.\n", query->id, context);
540         }
541         else
542         {
543             WARN("Occlusion queries not supported, not allocating query id.\n");
544             query->id = 0;
545         }
546     }
547
548     query->context = context;
549     list_add_head(&context->occlusion_queries, &query->entry);
550 }
551
552 void context_free_occlusion_query(struct wined3d_occlusion_query *query)
553 {
554     struct wined3d_context *context = query->context;
555
556     list_remove(&query->entry);
557     query->context = NULL;
558
559     if (context->free_occlusion_query_count >= context->free_occlusion_query_size - 1)
560     {
561         UINT new_size = context->free_occlusion_query_size << 1;
562         GLuint *new_data = HeapReAlloc(GetProcessHeap(), 0, context->free_occlusion_queries,
563                 new_size * sizeof(*context->free_occlusion_queries));
564
565         if (!new_data)
566         {
567             ERR("Failed to grow free list, leaking query %u in context %p.\n", query->id, context);
568             return;
569         }
570
571         context->free_occlusion_query_size = new_size;
572         context->free_occlusion_queries = new_data;
573     }
574
575     context->free_occlusion_queries[context->free_occlusion_query_count++] = query->id;
576 }
577
578 /* Context activation is done by the caller. */
579 void context_alloc_event_query(struct wined3d_context *context, struct wined3d_event_query *query)
580 {
581     const struct wined3d_gl_info *gl_info = context->gl_info;
582
583     if (context->free_event_query_count)
584     {
585         query->object = context->free_event_queries[--context->free_event_query_count];
586     }
587     else
588     {
589         if (gl_info->supported[ARB_SYNC])
590         {
591             /* Using ARB_sync, not much to do here. */
592             query->object.sync = NULL;
593             TRACE("Allocated event query %p in context %p.\n", query->object.sync, context);
594         }
595         else if (gl_info->supported[APPLE_FENCE])
596         {
597             ENTER_GL();
598             GL_EXTCALL(glGenFencesAPPLE(1, &query->object.id));
599             checkGLcall("glGenFencesAPPLE");
600             LEAVE_GL();
601
602             TRACE("Allocated event query %u in context %p.\n", query->object.id, context);
603         }
604         else if(gl_info->supported[NV_FENCE])
605         {
606             ENTER_GL();
607             GL_EXTCALL(glGenFencesNV(1, &query->object.id));
608             checkGLcall("glGenFencesNV");
609             LEAVE_GL();
610
611             TRACE("Allocated event query %u in context %p.\n", query->object.id, context);
612         }
613         else
614         {
615             WARN("Event queries not supported, not allocating query id.\n");
616             query->object.id = 0;
617         }
618     }
619
620     query->context = context;
621     list_add_head(&context->event_queries, &query->entry);
622 }
623
624 void context_free_event_query(struct wined3d_event_query *query)
625 {
626     struct wined3d_context *context = query->context;
627
628     list_remove(&query->entry);
629     query->context = NULL;
630
631     if (context->free_event_query_count >= context->free_event_query_size - 1)
632     {
633         UINT new_size = context->free_event_query_size << 1;
634         union wined3d_gl_query_object *new_data = HeapReAlloc(GetProcessHeap(), 0, context->free_event_queries,
635                 new_size * sizeof(*context->free_event_queries));
636
637         if (!new_data)
638         {
639             ERR("Failed to grow free list, leaking query %u in context %p.\n", query->object.id, context);
640             return;
641         }
642
643         context->free_event_query_size = new_size;
644         context->free_event_queries = new_data;
645     }
646
647     context->free_event_queries[context->free_event_query_count++] = query->object;
648 }
649
650 typedef void (context_fbo_entry_func_t)(struct wined3d_context *context, struct fbo_entry *entry);
651
652 static void context_enum_surface_fbo_entries(IWineD3DDeviceImpl *device,
653         IWineD3DSurfaceImpl *surface, context_fbo_entry_func_t *callback)
654 {
655     UINT i;
656
657     for (i = 0; i < device->context_count; ++i)
658     {
659         struct wined3d_context *context = device->contexts[i];
660         const struct wined3d_gl_info *gl_info = context->gl_info;
661         struct fbo_entry *entry, *entry2;
662
663         if (context->current_rt == surface) context->current_rt = NULL;
664
665         LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry)
666         {
667             UINT j;
668
669             if (entry->depth_stencil == surface)
670             {
671                 callback(context, entry);
672                 continue;
673             }
674
675             for (j = 0; j < gl_info->limits.buffers; ++j)
676             {
677                 if (entry->render_targets[j] == surface)
678                 {
679                     callback(context, entry);
680                     break;
681                 }
682             }
683         }
684     }
685 }
686
687 static void context_queue_fbo_entry_destruction(struct wined3d_context *context, struct fbo_entry *entry)
688 {
689     list_remove(&entry->entry);
690     list_add_head(&context->fbo_destroy_list, &entry->entry);
691 }
692
693 void context_resource_released(struct IWineD3DDeviceImpl *device,
694         struct wined3d_resource *resource, WINED3DRESOURCETYPE type)
695 {
696     if (!device->d3d_initialized) return;
697
698     switch (type)
699     {
700         case WINED3DRTYPE_SURFACE:
701             context_enum_surface_fbo_entries(device, surface_from_resource(resource),
702                     context_queue_fbo_entry_destruction);
703             break;
704
705         default:
706             break;
707     }
708 }
709
710 static void context_detach_fbo_entry(struct wined3d_context *context, struct fbo_entry *entry)
711 {
712     entry->attached = FALSE;
713 }
714
715 void context_resource_unloaded(struct IWineD3DDeviceImpl *device,
716         struct wined3d_resource *resource, WINED3DRESOURCETYPE type)
717 {
718     switch (type)
719     {
720         case WINED3DRTYPE_SURFACE:
721             context_enum_surface_fbo_entries(device, surface_from_resource(resource),
722                     context_detach_fbo_entry);
723             break;
724
725         default:
726             break;
727     }
728 }
729
730 void context_surface_update(struct wined3d_context *context, IWineD3DSurfaceImpl *surface)
731 {
732     const struct wined3d_gl_info *gl_info = context->gl_info;
733     struct fbo_entry *entry = context->current_fbo;
734     unsigned int i;
735
736     if (!entry || context->rebind_fbo) return;
737
738     for (i = 0; i < gl_info->limits.buffers; ++i)
739     {
740         if (surface == entry->render_targets[i])
741         {
742             TRACE("Updated surface %p is bound as color attachment %u to the current FBO.\n", surface, i);
743             context->rebind_fbo = TRUE;
744             return;
745         }
746     }
747
748     if (surface == entry->depth_stencil)
749     {
750         TRACE("Updated surface %p is bound as depth attachment to the current FBO.\n", surface);
751         context->rebind_fbo = TRUE;
752     }
753 }
754
755 static BOOL context_set_pixel_format(const struct wined3d_gl_info *gl_info, HDC dc, int format)
756 {
757     int current = GetPixelFormat(dc);
758
759     if (current == format) return TRUE;
760
761     if (!current)
762     {
763         if (!SetPixelFormat(dc, format, NULL))
764         {
765             ERR("Failed to set pixel format %d on device context %p, last error %#x.\n",
766                     format, dc, GetLastError());
767             return FALSE;
768         }
769         return TRUE;
770     }
771
772     /* By default WGL doesn't allow pixel format adjustments but we need it
773      * here. For this reason there's a Wine specific wglSetPixelFormat()
774      * which allows us to set the pixel format multiple times. Only use it
775      * when really needed. */
776     if (gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH])
777     {
778         if (!GL_EXTCALL(wglSetPixelFormatWINE(dc, format, NULL)))
779         {
780             ERR("wglSetPixelFormatWINE failed to set pixel format %d on device context %p.\n",
781                     format, dc);
782             return FALSE;
783         }
784         return TRUE;
785     }
786
787     /* OpenGL doesn't allow pixel format adjustments. Print an error and
788      * continue using the old format. There's a big chance that the old
789      * format works although with a performance hit and perhaps rendering
790      * errors. */
791     ERR("Unable to set pixel format %d on device context %p. Already using format %d.\n",
792             format, dc, current);
793     return TRUE;
794 }
795
796 static BOOL context_set_gl_context(struct wined3d_context *ctx)
797 {
798     struct wined3d_swapchain *swapchain = ctx->swapchain;
799
800     if (!pwglMakeCurrent(ctx->hdc, ctx->glCtx))
801     {
802         WARN("Failed to make GL context %p current on device context %p, last error %#x.\n",
803                 ctx->glCtx, ctx->hdc, GetLastError());
804         ctx->valid = 0;
805         WARN("Trying fallback to the backup window.\n");
806
807         if (!swapchain->backup_dc)
808         {
809             TRACE("Creating the backup window for swapchain %p.\n", swapchain);
810             swapchain->backup_wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
811                     WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
812             if (!swapchain->backup_wnd)
813             {
814                 ERR("Failed to create a window.\n");
815                 goto fail;
816             }
817             swapchain->backup_dc = GetDC(swapchain->backup_wnd);
818             if (!swapchain->backup_dc)
819             {
820                 ERR("Failed to get a DC.\n");
821                 goto fail;
822             }
823             if (!context_set_pixel_format(ctx->gl_info, swapchain->backup_dc, ctx->pixel_format))
824             {
825                 ERR("Failed to set pixel format %d on device context %p.\n",
826                         ctx->pixel_format, swapchain->backup_dc);
827                 goto fail;
828             }
829         }
830
831         if (!pwglMakeCurrent(swapchain->backup_dc, ctx->glCtx))
832         {
833             ERR("Fallback to backup window (dc %p) failed too, last error %#x.\n",
834                     swapchain->backup_dc, GetLastError());
835             context_set_current(NULL);
836             return FALSE;
837         }
838     }
839     return TRUE;
840
841 fail:
842     if (swapchain->backup_dc)
843     {
844         ReleaseDC(swapchain->backup_wnd, swapchain->backup_dc);
845         swapchain->backup_dc = NULL;
846     }
847     if (swapchain->backup_wnd)
848     {
849         DestroyWindow(swapchain->backup_wnd);
850         swapchain->backup_wnd = NULL;
851     }
852     context_set_current(NULL);
853     return FALSE;
854 }
855
856 static void context_restore_gl_context(HDC dc, HGLRC gl_ctx)
857 {
858     if (!pwglMakeCurrent(dc, gl_ctx))
859     {
860         ERR("Failed to restore GL context %p on device context %p, last error %#x.\n",
861                 gl_ctx, dc, GetLastError());
862         context_set_current(NULL);
863     }
864 }
865
866 static void context_update_window(struct wined3d_context *context)
867 {
868     if (context->win_handle == context->swapchain->win_handle)
869         return;
870
871     TRACE("Updating context %p window from %p to %p.\n",
872             context, context->win_handle, context->swapchain->win_handle);
873
874     if (context->valid)
875     {
876         /* You'd figure ReleaseDC() would fail if the DC doesn't match the
877          * window. However, that's not what actually happens, and there are
878          * user32 tests that confirm ReleaseDC() with the wrong window is
879          * supposed to succeed. So explicitly check that the DC belongs to
880          * the window, since we want to avoid releasing a DC that belongs to
881          * some other window if the original window was already destroyed. */
882         if (WindowFromDC(context->hdc) != context->win_handle)
883         {
884             WARN("DC %p does not belong to window %p.\n",
885                     context->hdc, context->win_handle);
886         }
887         else if (!ReleaseDC(context->win_handle, context->hdc))
888         {
889             ERR("Failed to release device context %p, last error %#x.\n",
890                     context->hdc, GetLastError());
891         }
892     }
893     else context->valid = 1;
894
895     context->win_handle = context->swapchain->win_handle;
896
897     if (!(context->hdc = GetDC(context->win_handle)))
898     {
899         ERR("Failed to get a device context for window %p.\n", context->win_handle);
900         goto err;
901     }
902
903     if (!context_set_pixel_format(context->gl_info, context->hdc, context->pixel_format))
904     {
905         ERR("Failed to set pixel format %d on device context %p.\n",
906                 context->pixel_format, context->hdc);
907         goto err;
908     }
909
910     context_set_gl_context(context);
911
912     return;
913
914 err:
915     context->valid = 0;
916 }
917
918 /* Do not call while under the GL lock. */
919 static void context_destroy_gl_resources(struct wined3d_context *context)
920 {
921     const struct wined3d_gl_info *gl_info = context->gl_info;
922     struct wined3d_occlusion_query *occlusion_query;
923     struct wined3d_event_query *event_query;
924     struct fbo_entry *entry, *entry2;
925     HGLRC restore_ctx;
926     HDC restore_dc;
927     unsigned int i;
928
929     restore_ctx = pwglGetCurrentContext();
930     restore_dc = pwglGetCurrentDC();
931
932     context_update_window(context);
933     if (context->valid && restore_ctx != context->glCtx)
934         context_set_gl_context(context);
935     else restore_ctx = NULL;
936
937     ENTER_GL();
938
939     LIST_FOR_EACH_ENTRY(occlusion_query, &context->occlusion_queries, struct wined3d_occlusion_query, entry)
940     {
941         if (context->valid && gl_info->supported[ARB_OCCLUSION_QUERY])
942             GL_EXTCALL(glDeleteQueriesARB(1, &occlusion_query->id));
943         occlusion_query->context = NULL;
944     }
945
946     LIST_FOR_EACH_ENTRY(event_query, &context->event_queries, struct wined3d_event_query, entry)
947     {
948         if (context->valid)
949         {
950             if (gl_info->supported[ARB_SYNC])
951             {
952                 if (event_query->object.sync) GL_EXTCALL(glDeleteSync(event_query->object.sync));
953             }
954             else if (gl_info->supported[APPLE_FENCE]) GL_EXTCALL(glDeleteFencesAPPLE(1, &event_query->object.id));
955             else if (gl_info->supported[NV_FENCE]) GL_EXTCALL(glDeleteFencesNV(1, &event_query->object.id));
956         }
957         event_query->context = NULL;
958     }
959
960     LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_destroy_list, struct fbo_entry, entry)
961     {
962         if (!context->valid) entry->id = 0;
963         context_destroy_fbo_entry(context, entry);
964     }
965
966     LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry)
967     {
968         if (!context->valid) entry->id = 0;
969         context_destroy_fbo_entry(context, entry);
970     }
971
972     if (context->valid)
973     {
974         if (context->dst_fbo)
975         {
976             TRACE("Destroy dst FBO %d\n", context->dst_fbo);
977             context_destroy_fbo(context, &context->dst_fbo);
978         }
979         if (context->dummy_arbfp_prog)
980         {
981             GL_EXTCALL(glDeleteProgramsARB(1, &context->dummy_arbfp_prog));
982         }
983
984         if (gl_info->supported[ARB_OCCLUSION_QUERY])
985             GL_EXTCALL(glDeleteQueriesARB(context->free_occlusion_query_count, context->free_occlusion_queries));
986
987         if (gl_info->supported[ARB_SYNC])
988         {
989             if (event_query->object.sync) GL_EXTCALL(glDeleteSync(event_query->object.sync));
990         }
991         else if (gl_info->supported[APPLE_FENCE])
992         {
993             for (i = 0; i < context->free_event_query_count; ++i)
994             {
995                 GL_EXTCALL(glDeleteFencesAPPLE(1, &context->free_event_queries[i].id));
996             }
997         }
998         else if (gl_info->supported[NV_FENCE])
999         {
1000             for (i = 0; i < context->free_event_query_count; ++i)
1001             {
1002                 GL_EXTCALL(glDeleteFencesNV(1, &context->free_event_queries[i].id));
1003             }
1004         }
1005
1006         checkGLcall("context cleanup");
1007     }
1008
1009     LEAVE_GL();
1010
1011     HeapFree(GetProcessHeap(), 0, context->free_occlusion_queries);
1012     HeapFree(GetProcessHeap(), 0, context->free_event_queries);
1013
1014     if (restore_ctx)
1015     {
1016         context_restore_gl_context(restore_dc, restore_ctx);
1017     }
1018     else if (pwglGetCurrentContext() && !pwglMakeCurrent(NULL, NULL))
1019     {
1020         ERR("Failed to disable GL context.\n");
1021     }
1022
1023     ReleaseDC(context->win_handle, context->hdc);
1024
1025     if (!pwglDeleteContext(context->glCtx))
1026     {
1027         DWORD err = GetLastError();
1028         ERR("wglDeleteContext(%p) failed, last error %#x.\n", context->glCtx, err);
1029     }
1030 }
1031
1032 DWORD context_get_tls_idx(void)
1033 {
1034     return wined3d_context_tls_idx;
1035 }
1036
1037 void context_set_tls_idx(DWORD idx)
1038 {
1039     wined3d_context_tls_idx = idx;
1040 }
1041
1042 struct wined3d_context *context_get_current(void)
1043 {
1044     return TlsGetValue(wined3d_context_tls_idx);
1045 }
1046
1047 /* Do not call while under the GL lock. */
1048 BOOL context_set_current(struct wined3d_context *ctx)
1049 {
1050     struct wined3d_context *old = context_get_current();
1051
1052     if (old == ctx)
1053     {
1054         TRACE("Already using D3D context %p.\n", ctx);
1055         return TRUE;
1056     }
1057
1058     if (old)
1059     {
1060         if (old->destroyed)
1061         {
1062             TRACE("Switching away from destroyed context %p.\n", old);
1063             context_destroy_gl_resources(old);
1064             HeapFree(GetProcessHeap(), 0, old);
1065         }
1066         else
1067         {
1068             old->current = 0;
1069         }
1070     }
1071
1072     if (ctx)
1073     {
1074         if (!ctx->valid)
1075         {
1076             ERR("Trying to make invalid context %p current\n", ctx);
1077             return FALSE;
1078         }
1079
1080         TRACE("Switching to D3D context %p, GL context %p, device context %p.\n", ctx, ctx->glCtx, ctx->hdc);
1081         if (!context_set_gl_context(ctx))
1082             return FALSE;
1083         ctx->current = 1;
1084     }
1085     else if(pwglGetCurrentContext())
1086     {
1087         TRACE("Clearing current D3D context.\n");
1088         if (!pwglMakeCurrent(NULL, NULL))
1089         {
1090             DWORD err = GetLastError();
1091             ERR("Failed to clear current GL context, last error %#x.\n", err);
1092             TlsSetValue(wined3d_context_tls_idx, NULL);
1093             return FALSE;
1094         }
1095     }
1096
1097     return TlsSetValue(wined3d_context_tls_idx, ctx);
1098 }
1099
1100 void context_release(struct wined3d_context *context)
1101 {
1102     TRACE("Releasing context %p, level %u.\n", context, context->level);
1103
1104     if (WARN_ON(d3d))
1105     {
1106         if (!context->level)
1107             WARN("Context %p is not active.\n", context);
1108         else if (context != context_get_current())
1109             WARN("Context %p is not the current context.\n", context);
1110     }
1111
1112     if (!--context->level && context->restore_ctx)
1113     {
1114         TRACE("Restoring GL context %p on device context %p.\n", context->restore_ctx, context->restore_dc);
1115         context_restore_gl_context(context->restore_dc, context->restore_ctx);
1116         context->restore_ctx = NULL;
1117         context->restore_dc = NULL;
1118     }
1119 }
1120
1121 static void context_enter(struct wined3d_context *context)
1122 {
1123     TRACE("Entering context %p, level %u.\n", context, context->level + 1);
1124
1125     if (!context->level++)
1126     {
1127         const struct wined3d_context *current_context = context_get_current();
1128         HGLRC current_gl = pwglGetCurrentContext();
1129
1130         if (current_gl && (!current_context || current_context->glCtx != current_gl))
1131         {
1132             TRACE("Another GL context (%p on device context %p) is already current.\n",
1133                     current_gl, pwglGetCurrentDC());
1134             context->restore_ctx = current_gl;
1135             context->restore_dc = pwglGetCurrentDC();
1136         }
1137     }
1138 }
1139
1140 /*****************************************************************************
1141  * Context_MarkStateDirty
1142  *
1143  * Marks a state in a context dirty. Only one context, opposed to
1144  * IWineD3DDeviceImpl_MarkStateDirty, which marks the state dirty in all
1145  * contexts
1146  *
1147  * Params:
1148  *  context: Context to mark the state dirty in
1149  *  state: State to mark dirty
1150  *  StateTable: Pointer to the state table in use(for state grouping)
1151  *
1152  *****************************************************************************/
1153 static void Context_MarkStateDirty(struct wined3d_context *context, DWORD state, const struct StateEntry *StateTable)
1154 {
1155     DWORD rep = StateTable[state].representative;
1156     DWORD idx;
1157     BYTE shift;
1158
1159     if (isStateDirty(context, rep)) return;
1160
1161     context->dirtyArray[context->numDirtyEntries++] = rep;
1162     idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT);
1163     shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
1164     context->isStateDirty[idx] |= (1 << shift);
1165 }
1166
1167 /* This function takes care of WineD3D pixel format selection. */
1168 static int WineD3D_ChoosePixelFormat(IWineD3DDeviceImpl *This, HDC hdc,
1169         const struct wined3d_format *color_format, const struct wined3d_format *ds_format,
1170         BOOL auxBuffers, int numSamples, BOOL findCompatible)
1171 {
1172     int iPixelFormat=0;
1173     unsigned int matchtry;
1174     short redBits, greenBits, blueBits, alphaBits, colorBits;
1175     short depthBits=0, stencilBits=0;
1176
1177     static const struct
1178     {
1179         BOOL require_aux;
1180         BOOL exact_alpha;
1181         BOOL exact_color;
1182     }
1183     matches[] =
1184     {
1185         /* First, try without alpha match buffers. MacOS supports aux buffers only
1186          * on A8R8G8B8, and we prefer better offscreen rendering over an alpha match.
1187          * Then try without aux buffers - this is the most common cause for not
1188          * finding a pixel format. Also some drivers(the open source ones)
1189          * only offer 32 bit ARB pixel formats. First try without an exact alpha
1190          * match, then try without an exact alpha and color match.
1191          */
1192         { TRUE,  TRUE,  TRUE  },
1193         { TRUE,  FALSE, TRUE  },
1194         { FALSE, TRUE,  TRUE  },
1195         { FALSE, FALSE, TRUE  },
1196         { TRUE,  FALSE, FALSE },
1197         { FALSE, FALSE, FALSE },
1198     };
1199
1200     int i = 0;
1201     int nCfgs = This->adapter->nCfgs;
1202
1203     TRACE("ColorFormat=%s, DepthStencilFormat=%s, auxBuffers=%d, numSamples=%d, findCompatible=%d\n",
1204           debug_d3dformat(color_format->id), debug_d3dformat(ds_format->id),
1205           auxBuffers, numSamples, findCompatible);
1206
1207     if (!getColorBits(color_format, &redBits, &greenBits, &blueBits, &alphaBits, &colorBits))
1208     {
1209         ERR("Unable to get color bits for format %s (%#x)!\n",
1210                 debug_d3dformat(color_format->id), color_format->id);
1211         return 0;
1212     }
1213
1214     getDepthStencilBits(ds_format, &depthBits, &stencilBits);
1215
1216     for(matchtry = 0; matchtry < (sizeof(matches) / sizeof(matches[0])) && !iPixelFormat; matchtry++) {
1217         for(i=0; i<nCfgs; i++) {
1218             BOOL exactDepthMatch = TRUE;
1219             WineD3D_PixelFormat *cfg = &This->adapter->cfgs[i];
1220
1221             /* For now only accept RGBA formats. Perhaps some day we will
1222              * allow floating point formats for pbuffers. */
1223             if(cfg->iPixelType != WGL_TYPE_RGBA_ARB)
1224                 continue;
1225
1226             /* In window mode we need a window drawable format and double buffering. */
1227             if(!(cfg->windowDrawable && cfg->doubleBuffer))
1228                 continue;
1229
1230             /* We like to have aux buffers in backbuffer mode */
1231             if(auxBuffers && !cfg->auxBuffers && matches[matchtry].require_aux)
1232                 continue;
1233
1234             if(matches[matchtry].exact_color) {
1235                 if(cfg->redSize != redBits)
1236                     continue;
1237                 if(cfg->greenSize != greenBits)
1238                     continue;
1239                 if(cfg->blueSize != blueBits)
1240                     continue;
1241             } else {
1242                 if(cfg->redSize < redBits)
1243                     continue;
1244                 if(cfg->greenSize < greenBits)
1245                     continue;
1246                 if(cfg->blueSize < blueBits)
1247                     continue;
1248             }
1249             if(matches[matchtry].exact_alpha) {
1250                 if(cfg->alphaSize != alphaBits)
1251                     continue;
1252             } else {
1253                 if(cfg->alphaSize < alphaBits)
1254                     continue;
1255             }
1256
1257             /* We try to locate a format which matches our requirements exactly. In case of
1258              * depth it is no problem to emulate 16-bit using e.g. 24-bit, so accept that. */
1259             if(cfg->depthSize < depthBits)
1260                 continue;
1261             else if(cfg->depthSize > depthBits)
1262                 exactDepthMatch = FALSE;
1263
1264             /* In all cases make sure the number of stencil bits matches our requirements
1265              * even when we don't need stencil because it could affect performance EXCEPT
1266              * on cards which don't offer depth formats without stencil like the i915 drivers
1267              * on Linux. */
1268             if(stencilBits != cfg->stencilSize && !(This->adapter->brokenStencil && stencilBits <= cfg->stencilSize))
1269                 continue;
1270
1271             /* Check multisampling support */
1272             if(cfg->numSamples != numSamples)
1273                 continue;
1274
1275             /* When we have passed all the checks then we have found a format which matches our
1276              * requirements. Note that we only check for a limit number of capabilities right now,
1277              * so there can easily be a dozen of pixel formats which appear to be the 'same' but
1278              * can still differ in things like multisampling, stereo, SRGB and other flags.
1279              */
1280
1281             /* Exit the loop as we have found a format :) */
1282             if(exactDepthMatch) {
1283                 iPixelFormat = cfg->iPixelFormat;
1284                 break;
1285             } else if(!iPixelFormat) {
1286                 /* In the end we might end up with a format which doesn't exactly match our depth
1287                  * requirements. Accept the first format we found because formats with higher iPixelFormat
1288                  * values tend to have more extended capabilities (e.g. multisampling) which we don't need. */
1289                 iPixelFormat = cfg->iPixelFormat;
1290             }
1291         }
1292     }
1293
1294     /* When findCompatible is set and no suitable format was found, let ChoosePixelFormat choose a pixel format in order not to crash. */
1295     if(!iPixelFormat && !findCompatible) {
1296         ERR("Can't find a suitable iPixelFormat\n");
1297         return FALSE;
1298     } else if(!iPixelFormat) {
1299         PIXELFORMATDESCRIPTOR pfd;
1300
1301         TRACE("Falling back to ChoosePixelFormat as we weren't able to find an exactly matching pixel format\n");
1302         /* PixelFormat selection */
1303         ZeroMemory(&pfd, sizeof(pfd));
1304         pfd.nSize      = sizeof(pfd);
1305         pfd.nVersion   = 1;
1306         pfd.dwFlags    = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
1307         pfd.iPixelType = PFD_TYPE_RGBA;
1308         pfd.cAlphaBits = alphaBits;
1309         pfd.cColorBits = colorBits;
1310         pfd.cDepthBits = depthBits;
1311         pfd.cStencilBits = stencilBits;
1312         pfd.iLayerType = PFD_MAIN_PLANE;
1313
1314         iPixelFormat = ChoosePixelFormat(hdc, &pfd);
1315         if(!iPixelFormat) {
1316             /* If this happens something is very wrong as ChoosePixelFormat barely fails */
1317             ERR("Can't find a suitable iPixelFormat\n");
1318             return FALSE;
1319         }
1320     }
1321
1322     TRACE("Found iPixelFormat=%d for ColorFormat=%s, DepthStencilFormat=%s\n",
1323             iPixelFormat, debug_d3dformat(color_format->id), debug_d3dformat(ds_format->id));
1324     return iPixelFormat;
1325 }
1326
1327 /* Do not call while under the GL lock. */
1328 struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
1329         IWineD3DSurfaceImpl *target, const struct wined3d_format *ds_format)
1330 {
1331     IWineD3DDeviceImpl *device = swapchain->device;
1332     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1333     const struct wined3d_format *color_format;
1334     struct wined3d_context *ret;
1335     PIXELFORMATDESCRIPTOR pfd;
1336     BOOL auxBuffers = FALSE;
1337     int numSamples = 0;
1338     int pixel_format;
1339     unsigned int s;
1340     int swap_interval;
1341     DWORD state;
1342     HGLRC ctx;
1343     HDC hdc;
1344
1345     TRACE("swapchain %p, target %p, window %p.\n", swapchain, target, swapchain->win_handle);
1346
1347     ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
1348     if (!ret)
1349     {
1350         ERR("Failed to allocate context memory.\n");
1351         return NULL;
1352     }
1353
1354     if (!(hdc = GetDC(swapchain->win_handle)))
1355     {
1356         ERR("Failed to retrieve a device context.\n");
1357         goto out;
1358     }
1359
1360     color_format = target->resource.format;
1361
1362     /* In case of ORM_BACKBUFFER, make sure to request an alpha component for
1363      * X4R4G4B4/X8R8G8B8 as we might need it for the backbuffer. */
1364     if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER)
1365     {
1366         auxBuffers = TRUE;
1367
1368         if (color_format->id == WINED3DFMT_B4G4R4X4_UNORM)
1369             color_format = wined3d_get_format(gl_info, WINED3DFMT_B4G4R4A4_UNORM);
1370         else if (color_format->id == WINED3DFMT_B8G8R8X8_UNORM)
1371             color_format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
1372     }
1373
1374     /* DirectDraw supports 8bit paletted render targets and these are used by
1375      * old games like Starcraft and C&C. Most modern hardware doesn't support
1376      * 8bit natively so we perform some form of 8bit -> 32bit conversion. The
1377      * conversion (ab)uses the alpha component for storing the palette index.
1378      * For this reason we require a format with 8bit alpha, so request
1379      * A8R8G8B8. */
1380     if (color_format->id == WINED3DFMT_P8_UINT)
1381         color_format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
1382
1383     /* D3D only allows multisampling when SwapEffect is set to WINED3DSWAPEFFECT_DISCARD. */
1384     if (swapchain->presentParms.MultiSampleType && (swapchain->presentParms.SwapEffect == WINED3DSWAPEFFECT_DISCARD))
1385     {
1386         if (!gl_info->supported[ARB_MULTISAMPLE])
1387             WARN("The application is requesting multisampling without support.\n");
1388         else
1389         {
1390             TRACE("Requesting multisample type %#x.\n", swapchain->presentParms.MultiSampleType);
1391             numSamples = swapchain->presentParms.MultiSampleType;
1392         }
1393     }
1394
1395     /* Try to find a pixel format which matches our requirements. */
1396     pixel_format = WineD3D_ChoosePixelFormat(device, hdc, color_format, ds_format,
1397             auxBuffers, numSamples, FALSE /* findCompatible */);
1398
1399     /* Try to locate a compatible format if we weren't able to find anything. */
1400     if (!pixel_format)
1401     {
1402         TRACE("Trying to locate a compatible pixel format because an exact match failed.\n");
1403         pixel_format = WineD3D_ChoosePixelFormat(device, hdc, color_format, ds_format,
1404                 auxBuffers, 0 /* numSamples */, TRUE /* findCompatible */);
1405     }
1406
1407     /* If we still don't have a pixel format, something is very wrong as ChoosePixelFormat barely fails */
1408     if (!pixel_format)
1409     {
1410         ERR("Can't find a suitable pixel format.\n");
1411         goto out;
1412     }
1413
1414     DescribePixelFormat(hdc, pixel_format, sizeof(pfd), &pfd);
1415     if (!context_set_pixel_format(gl_info, hdc, pixel_format))
1416     {
1417         ERR("Failed to set pixel format %d on device context %p.\n", pixel_format, hdc);
1418         goto out;
1419     }
1420
1421     ctx = pwglCreateContext(hdc);
1422     if (device->context_count)
1423     {
1424         if (!pwglShareLists(device->contexts[0]->glCtx, ctx))
1425         {
1426             DWORD err = GetLastError();
1427             ERR("wglShareLists(%p, %p) failed, last error %#x.\n",
1428                     device->contexts[0]->glCtx, ctx, err);
1429         }
1430     }
1431
1432     if(!ctx) {
1433         ERR("Failed to create a WGL context\n");
1434         goto out;
1435     }
1436
1437     if (!device_context_add(device, ret))
1438     {
1439         ERR("Failed to add the newly created context to the context list\n");
1440         if (!pwglDeleteContext(ctx))
1441         {
1442             DWORD err = GetLastError();
1443             ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx, err);
1444         }
1445         goto out;
1446     }
1447
1448     ret->gl_info = gl_info;
1449
1450     /* Mark all states dirty to force a proper initialization of the states
1451      * on the first use of the context. */
1452     for (state = 0; state <= STATE_HIGHEST; ++state)
1453     {
1454         if (device->StateTable[state].representative)
1455             Context_MarkStateDirty(ret, state, device->StateTable);
1456     }
1457
1458     ret->swapchain = swapchain;
1459     ret->current_rt = target;
1460     ret->tid = GetCurrentThreadId();
1461
1462     ret->render_offscreen = surface_is_offscreen(target);
1463     ret->draw_buffer_dirty = TRUE;
1464     ret->valid = 1;
1465
1466     ret->glCtx = ctx;
1467     ret->win_handle = swapchain->win_handle;
1468     ret->hdc = hdc;
1469     ret->pixel_format = pixel_format;
1470
1471     if (device->shader_backend->shader_dirtifyable_constants())
1472     {
1473         /* Create the dirty constants array and initialize them to dirty */
1474         ret->vshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
1475                 sizeof(*ret->vshader_const_dirty) * device->d3d_vshader_constantF);
1476         ret->pshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
1477                 sizeof(*ret->pshader_const_dirty) * device->d3d_pshader_constantF);
1478         memset(ret->vshader_const_dirty, 1,
1479                sizeof(*ret->vshader_const_dirty) * device->d3d_vshader_constantF);
1480         memset(ret->pshader_const_dirty, 1,
1481                 sizeof(*ret->pshader_const_dirty) * device->d3d_pshader_constantF);
1482     }
1483
1484     ret->blit_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1485             gl_info->limits.buffers * sizeof(*ret->blit_targets));
1486     if (!ret->blit_targets) goto out;
1487
1488     ret->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1489             gl_info->limits.buffers * sizeof(*ret->draw_buffers));
1490     if (!ret->draw_buffers) goto out;
1491
1492     ret->free_occlusion_query_size = 4;
1493     ret->free_occlusion_queries = HeapAlloc(GetProcessHeap(), 0,
1494             ret->free_occlusion_query_size * sizeof(*ret->free_occlusion_queries));
1495     if (!ret->free_occlusion_queries) goto out;
1496
1497     list_init(&ret->occlusion_queries);
1498
1499     ret->free_event_query_size = 4;
1500     ret->free_event_queries = HeapAlloc(GetProcessHeap(), 0,
1501             ret->free_event_query_size * sizeof(*ret->free_event_queries));
1502     if (!ret->free_event_queries) goto out;
1503
1504     list_init(&ret->event_queries);
1505
1506     TRACE("Successfully created new context %p\n", ret);
1507
1508     list_init(&ret->fbo_list);
1509     list_init(&ret->fbo_destroy_list);
1510
1511     context_enter(ret);
1512
1513     /* Set up the context defaults */
1514     if (!context_set_current(ret))
1515     {
1516         ERR("Cannot activate context to set up defaults\n");
1517         context_release(ret);
1518         goto out;
1519     }
1520
1521     switch (swapchain->presentParms.PresentationInterval)
1522     {
1523         case WINED3DPRESENT_INTERVAL_IMMEDIATE:
1524             swap_interval = 0;
1525             break;
1526         case WINED3DPRESENT_INTERVAL_DEFAULT:
1527         case WINED3DPRESENT_INTERVAL_ONE:
1528             swap_interval = 1;
1529             break;
1530         case WINED3DPRESENT_INTERVAL_TWO:
1531             swap_interval = 2;
1532             break;
1533         case WINED3DPRESENT_INTERVAL_THREE:
1534             swap_interval = 3;
1535             break;
1536         case WINED3DPRESENT_INTERVAL_FOUR:
1537             swap_interval = 4;
1538             break;
1539         default:
1540             FIXME("Unknown presentation interval %08x\n", swapchain->presentParms.PresentationInterval);
1541             swap_interval = 1;
1542     }
1543
1544     if (gl_info->supported[WGL_EXT_SWAP_CONTROL])
1545     {
1546         if (!GL_EXTCALL(wglSwapIntervalEXT(swap_interval)))
1547             ERR("wglSwapIntervalEXT failed to set swap interval %d for context %p, last error %#x\n",
1548                 swap_interval, ret, GetLastError());
1549     }
1550
1551     ENTER_GL();
1552
1553     glGetIntegerv(GL_AUX_BUFFERS, &ret->aux_buffers);
1554
1555     TRACE("Setting up the screen\n");
1556     /* Clear the screen */
1557     glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
1558     checkGLcall("glClearColor");
1559     glClearIndex(0);
1560     glClearDepth(1);
1561     glClearStencil(0xffff);
1562
1563     checkGLcall("glClear");
1564
1565     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1566     checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1567
1568     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1569     checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1570
1571     glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1572     checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1573
1574     glPixelStorei(GL_PACK_ALIGNMENT, device->surface_alignment);
1575     checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, device->surface_alignment);");
1576     glPixelStorei(GL_UNPACK_ALIGNMENT, device->surface_alignment);
1577     checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, device->surface_alignment);");
1578
1579     if (gl_info->supported[APPLE_CLIENT_STORAGE])
1580     {
1581         /* Most textures will use client storage if supported. Exceptions are non-native power of 2 textures
1582          * and textures in DIB sections(due to the memory protection).
1583          */
1584         glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
1585         checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
1586     }
1587     if (gl_info->supported[ARB_VERTEX_BLEND])
1588     {
1589         /* Direct3D always uses n-1 weights for n world matrices and uses 1 - sum for the last one
1590          * this is equal to GL_WEIGHT_SUM_UNITY_ARB. Enabling it doesn't do anything unless
1591          * GL_VERTEX_BLEND_ARB isn't enabled too
1592          */
1593         glEnable(GL_WEIGHT_SUM_UNITY_ARB);
1594         checkGLcall("glEnable(GL_WEIGHT_SUM_UNITY_ARB)");
1595     }
1596     if (gl_info->supported[NV_TEXTURE_SHADER2])
1597     {
1598         /* Set up the previous texture input for all shader units. This applies to bump mapping, and in d3d
1599          * the previous texture where to source the offset from is always unit - 1.
1600          */
1601         for (s = 1; s < gl_info->limits.textures; ++s)
1602         {
1603             GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + s));
1604             glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + s - 1);
1605             checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, ...");
1606         }
1607     }
1608     if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1609     {
1610         /* MacOS(radeon X1600 at least, but most likely others too) refuses to draw if GLSL and ARBFP are
1611          * enabled, but the currently bound arbfp program is 0. Enabling ARBFP with prog 0 is invalid, but
1612          * GLSL should bypass this. This causes problems in programs that never use the fixed function pipeline,
1613          * because the ARBFP extension is enabled by the ARBFP pipeline at context creation, but no program
1614          * is ever assigned.
1615          *
1616          * So make sure a program is assigned to each context. The first real ARBFP use will set a different
1617          * program and the dummy program is destroyed when the context is destroyed.
1618          */
1619         const char *dummy_program =
1620                 "!!ARBfp1.0\n"
1621                 "MOV result.color, fragment.color.primary;\n"
1622                 "END\n";
1623         GL_EXTCALL(glGenProgramsARB(1, &ret->dummy_arbfp_prog));
1624         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ret->dummy_arbfp_prog));
1625         GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(dummy_program), dummy_program));
1626     }
1627
1628     for (s = 0; s < gl_info->limits.point_sprite_units; ++s)
1629     {
1630         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + s));
1631         glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
1632         checkGLcall("glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)");
1633     }
1634
1635     if (gl_info->supported[ARB_PROVOKING_VERTEX])
1636     {
1637         GL_EXTCALL(glProvokingVertex(GL_FIRST_VERTEX_CONVENTION));
1638     }
1639     else if (gl_info->supported[EXT_PROVOKING_VERTEX])
1640     {
1641         GL_EXTCALL(glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT));
1642     }
1643
1644     LEAVE_GL();
1645
1646     device->frag_pipe->enable_extension(TRUE);
1647
1648     TRACE("Created context %p.\n", ret);
1649
1650     return ret;
1651
1652 out:
1653     HeapFree(GetProcessHeap(), 0, ret->free_event_queries);
1654     HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries);
1655     HeapFree(GetProcessHeap(), 0, ret->draw_buffers);
1656     HeapFree(GetProcessHeap(), 0, ret->blit_targets);
1657     HeapFree(GetProcessHeap(), 0, ret->pshader_const_dirty);
1658     HeapFree(GetProcessHeap(), 0, ret->vshader_const_dirty);
1659     HeapFree(GetProcessHeap(), 0, ret);
1660     return NULL;
1661 }
1662
1663 /* Do not call while under the GL lock. */
1664 void context_destroy(IWineD3DDeviceImpl *This, struct wined3d_context *context)
1665 {
1666     BOOL destroy;
1667
1668     TRACE("Destroying ctx %p\n", context);
1669
1670     if (context->tid == GetCurrentThreadId() || !context->current)
1671     {
1672         context_destroy_gl_resources(context);
1673         TlsSetValue(wined3d_context_tls_idx, NULL);
1674         destroy = TRUE;
1675     }
1676     else
1677     {
1678         context->destroyed = 1;
1679         destroy = FALSE;
1680     }
1681
1682     HeapFree(GetProcessHeap(), 0, context->draw_buffers);
1683     HeapFree(GetProcessHeap(), 0, context->blit_targets);
1684     HeapFree(GetProcessHeap(), 0, context->vshader_const_dirty);
1685     HeapFree(GetProcessHeap(), 0, context->pshader_const_dirty);
1686     device_context_remove(This, context);
1687     if (destroy) HeapFree(GetProcessHeap(), 0, context);
1688 }
1689
1690 /* GL locking is done by the caller */
1691 static inline void set_blit_dimension(UINT width, UINT height) {
1692     glMatrixMode(GL_PROJECTION);
1693     checkGLcall("glMatrixMode(GL_PROJECTION)");
1694     glLoadIdentity();
1695     checkGLcall("glLoadIdentity()");
1696     glOrtho(0, width, 0, height, 0.0, -1.0);
1697     checkGLcall("glOrtho");
1698     glViewport(0, 0, width, height);
1699     checkGLcall("glViewport");
1700 }
1701
1702 /*****************************************************************************
1703  * SetupForBlit
1704  *
1705  * Sets up a context for DirectDraw blitting.
1706  * All texture units are disabled, texture unit 0 is set as current unit
1707  * fog, lighting, blending, alpha test, z test, scissor test, culling disabled
1708  * color writing enabled for all channels
1709  * register combiners disabled, shaders disabled
1710  * world matrix is set to identity, texture matrix 0 too
1711  * projection matrix is setup for drawing screen coordinates
1712  *
1713  * Params:
1714  *  This: Device to activate the context for
1715  *  context: Context to setup
1716  *
1717  *****************************************************************************/
1718 /* Context activation is done by the caller. */
1719 static void SetupForBlit(IWineD3DDeviceImpl *This, struct wined3d_context *context)
1720 {
1721     int i;
1722     const struct StateEntry *StateTable = This->StateTable;
1723     const struct wined3d_gl_info *gl_info = context->gl_info;
1724     UINT width = context->current_rt->resource.width;
1725     UINT height = context->current_rt->resource.height;
1726     DWORD sampler;
1727
1728     TRACE("Setting up context %p for blitting\n", context);
1729     if(context->last_was_blit) {
1730         if(context->blit_w != width || context->blit_h != height) {
1731             ENTER_GL();
1732             set_blit_dimension(width, height);
1733             LEAVE_GL();
1734             context->blit_w = width; context->blit_h = height;
1735             /* No need to dirtify here, the states are still dirtified because they weren't
1736              * applied since the last SetupForBlit call. Otherwise last_was_blit would not
1737              * be set
1738              */
1739         }
1740         TRACE("Context is already set up for blitting, nothing to do\n");
1741         return;
1742     }
1743     context->last_was_blit = TRUE;
1744
1745     /* TODO: Use a display list */
1746
1747     /* Disable shaders */
1748     ENTER_GL();
1749     This->shader_backend->shader_select(context, FALSE, FALSE);
1750     LEAVE_GL();
1751
1752     Context_MarkStateDirty(context, STATE_VSHADER, StateTable);
1753     Context_MarkStateDirty(context, STATE_PIXELSHADER, StateTable);
1754
1755     /* Call ENTER_GL() once for all gl calls below. In theory we should not call
1756      * helper functions in between gl calls. This function is full of Context_MarkStateDirty
1757      * which can safely be called from here, we only lock once instead locking/unlocking
1758      * after each GL call.
1759      */
1760     ENTER_GL();
1761
1762     /* Disable all textures. The caller can then bind a texture it wants to blit
1763      * from
1764      *
1765      * The blitting code uses (for now) the fixed function pipeline, so make sure to reset all fixed
1766      * function texture unit. No need to care for higher samplers
1767      */
1768     for (i = gl_info->limits.textures - 1; i > 0 ; --i)
1769     {
1770         sampler = This->rev_tex_unit_map[i];
1771         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
1772         checkGLcall("glActiveTextureARB");
1773
1774         if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
1775         {
1776             glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1777             checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
1778         }
1779         glDisable(GL_TEXTURE_3D);
1780         checkGLcall("glDisable GL_TEXTURE_3D");
1781         if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
1782         {
1783             glDisable(GL_TEXTURE_RECTANGLE_ARB);
1784             checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
1785         }
1786         glDisable(GL_TEXTURE_2D);
1787         checkGLcall("glDisable GL_TEXTURE_2D");
1788
1789         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1790         checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);");
1791
1792         if (sampler != WINED3D_UNMAPPED_STAGE)
1793         {
1794             if (sampler < MAX_TEXTURES) {
1795                 Context_MarkStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP), StateTable);
1796             }
1797             Context_MarkStateDirty(context, STATE_SAMPLER(sampler), StateTable);
1798         }
1799     }
1800     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
1801     checkGLcall("glActiveTextureARB");
1802
1803     sampler = This->rev_tex_unit_map[0];
1804
1805     if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
1806     {
1807         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1808         checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
1809     }
1810     glDisable(GL_TEXTURE_3D);
1811     checkGLcall("glDisable GL_TEXTURE_3D");
1812     if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
1813     {
1814         glDisable(GL_TEXTURE_RECTANGLE_ARB);
1815         checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
1816     }
1817     glDisable(GL_TEXTURE_2D);
1818     checkGLcall("glDisable GL_TEXTURE_2D");
1819
1820     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1821
1822     glMatrixMode(GL_TEXTURE);
1823     checkGLcall("glMatrixMode(GL_TEXTURE)");
1824     glLoadIdentity();
1825     checkGLcall("glLoadIdentity()");
1826
1827     if (gl_info->supported[EXT_TEXTURE_LOD_BIAS])
1828     {
1829         glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
1830                   GL_TEXTURE_LOD_BIAS_EXT,
1831                   0.0f);
1832         checkGLcall("glTexEnvf GL_TEXTURE_LOD_BIAS_EXT ...");
1833     }
1834
1835     if (sampler != WINED3D_UNMAPPED_STAGE)
1836     {
1837         if (sampler < MAX_TEXTURES) {
1838             Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + sampler), StateTable);
1839             Context_MarkStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP), StateTable);
1840         }
1841         Context_MarkStateDirty(context, STATE_SAMPLER(sampler), StateTable);
1842     }
1843
1844     /* Other misc states */
1845     glDisable(GL_ALPHA_TEST);
1846     checkGLcall("glDisable(GL_ALPHA_TEST)");
1847     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHATESTENABLE), StateTable);
1848     glDisable(GL_LIGHTING);
1849     checkGLcall("glDisable GL_LIGHTING");
1850     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING), StateTable);
1851     glDisable(GL_DEPTH_TEST);
1852     checkGLcall("glDisable GL_DEPTH_TEST");
1853     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ZENABLE), StateTable);
1854     glDisableWINE(GL_FOG);
1855     checkGLcall("glDisable GL_FOG");
1856     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_FOGENABLE), StateTable);
1857     glDisable(GL_BLEND);
1858     checkGLcall("glDisable GL_BLEND");
1859     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
1860     glDisable(GL_CULL_FACE);
1861     checkGLcall("glDisable GL_CULL_FACE");
1862     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_CULLMODE), StateTable);
1863     glDisable(GL_STENCIL_TEST);
1864     checkGLcall("glDisable GL_STENCIL_TEST");
1865     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_STENCILENABLE), StateTable);
1866     glDisable(GL_SCISSOR_TEST);
1867     checkGLcall("glDisable GL_SCISSOR_TEST");
1868     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), StateTable);
1869     if (gl_info->supported[ARB_POINT_SPRITE])
1870     {
1871         glDisable(GL_POINT_SPRITE_ARB);
1872         checkGLcall("glDisable GL_POINT_SPRITE_ARB");
1873         Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), StateTable);
1874     }
1875     glColorMask(GL_TRUE, GL_TRUE,GL_TRUE,GL_TRUE);
1876     checkGLcall("glColorMask");
1877     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE), StateTable);
1878     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), StateTable);
1879     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), StateTable);
1880     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), StateTable);
1881     if (gl_info->supported[EXT_SECONDARY_COLOR])
1882     {
1883         glDisable(GL_COLOR_SUM_EXT);
1884         Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SPECULARENABLE), StateTable);
1885         checkGLcall("glDisable(GL_COLOR_SUM_EXT)");
1886     }
1887
1888     /* Setup transforms */
1889     glMatrixMode(GL_MODELVIEW);
1890     checkGLcall("glMatrixMode(GL_MODELVIEW)");
1891     glLoadIdentity();
1892     checkGLcall("glLoadIdentity()");
1893     Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), StateTable);
1894
1895     context->last_was_rhw = TRUE;
1896     Context_MarkStateDirty(context, STATE_VDECL, StateTable); /* because of last_was_rhw = TRUE */
1897
1898     glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)");
1899     glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)");
1900     glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)");
1901     glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)");
1902     glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)");
1903     glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)");
1904     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPING), StateTable);
1905
1906     set_blit_dimension(width, height);
1907
1908     LEAVE_GL();
1909
1910     context->blit_w = width; context->blit_h = height;
1911     Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable);
1912     Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION), StateTable);
1913
1914     This->frag_pipe->enable_extension(FALSE);
1915 }
1916
1917 /* Do not call while under the GL lock. */
1918 static struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target)
1919 {
1920     struct wined3d_context *current_context = context_get_current();
1921     struct wined3d_context *context;
1922
1923     if (current_context && current_context->destroyed) current_context = NULL;
1924
1925     if (!target)
1926     {
1927         if (current_context
1928                 && current_context->current_rt
1929                 && current_context->swapchain->device == This)
1930         {
1931             target = current_context->current_rt;
1932         }
1933         else
1934         {
1935             struct wined3d_swapchain *swapchain = This->swapchains[0];
1936             if (swapchain->back_buffers) target = swapchain->back_buffers[0];
1937             else target = swapchain->front_buffer;
1938         }
1939     }
1940
1941     if (current_context && current_context->current_rt == target)
1942     {
1943         context_update_window(current_context);
1944         return current_context;
1945     }
1946
1947     if (target->container.type == WINED3D_CONTAINER_SWAPCHAIN)
1948     {
1949         TRACE("Rendering onscreen\n");
1950
1951         context = swapchain_get_context(target->container.u.swapchain);
1952     }
1953     else
1954     {
1955         TRACE("Rendering offscreen\n");
1956
1957         /* Stay with the current context if possible. Otherwise use the
1958          * context for the primary swapchain. */
1959         if (current_context && current_context->swapchain->device == This)
1960             context = current_context;
1961         else
1962             context = swapchain_get_context(This->swapchains[0]);
1963     }
1964
1965     context_update_window(context);
1966
1967     return context;
1968 }
1969
1970 /* Context activation is done by the caller. */
1971 static void context_apply_draw_buffers(struct wined3d_context *context, UINT rt_count, IWineD3DSurfaceImpl **rts)
1972 {
1973     if (!rt_count)
1974     {
1975         ENTER_GL();
1976         glDrawBuffer(GL_NONE);
1977         checkGLcall("glDrawBuffer()");
1978         LEAVE_GL();
1979     }
1980     else if (!surface_is_offscreen(rts[0]))
1981     {
1982         ENTER_GL();
1983         glDrawBuffer(surface_get_gl_buffer(rts[0]));
1984         checkGLcall("glDrawBuffer()");
1985         LEAVE_GL();
1986     }
1987     else
1988     {
1989         ENTER_GL();
1990         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
1991         {
1992             const struct wined3d_gl_info *gl_info = context->gl_info;
1993             unsigned int i;
1994
1995             for (i = 0; i < rt_count; ++i)
1996             {
1997                 if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL)
1998                     context->draw_buffers[i] = GL_COLOR_ATTACHMENT0 + i;
1999                 else
2000                     context->draw_buffers[i] = GL_NONE;
2001             }
2002
2003             if (gl_info->supported[ARB_DRAW_BUFFERS])
2004             {
2005                 GL_EXTCALL(glDrawBuffersARB(rt_count, context->draw_buffers));
2006                 checkGLcall("glDrawBuffers()");
2007             }
2008             else
2009             {
2010                 glDrawBuffer(context->draw_buffers[0]);
2011                 checkGLcall("glDrawBuffer()");
2012             }
2013         }
2014         else
2015         {
2016             glDrawBuffer(rts[0]->resource.device->offscreenBuffer);
2017             checkGLcall("glDrawBuffer()");
2018         }
2019         LEAVE_GL();
2020     }
2021 }
2022
2023 /* GL locking is done by the caller. */
2024 void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer)
2025 {
2026     glDrawBuffer(buffer);
2027     checkGLcall("glDrawBuffer()");
2028     context->draw_buffer_dirty = TRUE;
2029 }
2030
2031 static inline void context_set_render_offscreen(struct wined3d_context *context, const struct StateEntry *StateTable,
2032         BOOL offscreen)
2033 {
2034     if (context->render_offscreen == offscreen) return;
2035
2036     Context_MarkStateDirty(context, STATE_POINTSPRITECOORDORIGIN, StateTable);
2037     Context_MarkStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION), StateTable);
2038     Context_MarkStateDirty(context, STATE_VIEWPORT, StateTable);
2039     Context_MarkStateDirty(context, STATE_SCISSORRECT, StateTable);
2040     Context_MarkStateDirty(context, STATE_FRONTFACE, StateTable);
2041     context->render_offscreen = offscreen;
2042 }
2043
2044 static BOOL match_depth_stencil_format(const struct wined3d_format *existing,
2045         const struct wined3d_format *required)
2046 {
2047     short existing_depth, existing_stencil, required_depth, required_stencil;
2048
2049     if (existing == required) return TRUE;
2050     if ((existing->flags & WINED3DFMT_FLAG_FLOAT) != (required->flags & WINED3DFMT_FLAG_FLOAT)) return FALSE;
2051
2052     getDepthStencilBits(existing, &existing_depth, &existing_stencil);
2053     getDepthStencilBits(required, &required_depth, &required_stencil);
2054
2055     if(existing_depth < required_depth) return FALSE;
2056     /* If stencil bits are used the exact amount is required - otherwise wrapping
2057      * won't work correctly */
2058     if(required_stencil && required_stencil != existing_stencil) return FALSE;
2059     return TRUE;
2060 }
2061 /* The caller provides a context */
2062 static void context_validate_onscreen_formats(IWineD3DDeviceImpl *device,
2063         struct wined3d_context *context, IWineD3DSurfaceImpl *depth_stencil)
2064 {
2065     /* Onscreen surfaces are always in a swapchain */
2066     struct wined3d_swapchain *swapchain = context->current_rt->container.u.swapchain;
2067
2068     if (context->render_offscreen || !depth_stencil) return;
2069     if (match_depth_stencil_format(swapchain->ds_format, depth_stencil->resource.format)) return;
2070
2071     /* TODO: If the requested format would satisfy the needs of the existing one(reverse match),
2072      * or no onscreen depth buffer was created, the OpenGL drawable could be changed to the new
2073      * format. */
2074     WARN("Depth stencil format is not supported by WGL, rendering the backbuffer in an FBO\n");
2075
2076     /* The currently active context is the necessary context to access the swapchain's onscreen buffers */
2077     surface_load_location(context->current_rt, SFLAG_INTEXTURE, NULL);
2078     swapchain->render_to_fbo = TRUE;
2079     context_set_render_offscreen(context, device->StateTable, TRUE);
2080 }
2081
2082 /* Context activation is done by the caller. */
2083 void context_apply_blit_state(struct wined3d_context *context, IWineD3DDeviceImpl *device)
2084 {
2085     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2086     {
2087         context_validate_onscreen_formats(device, context, NULL);
2088
2089         if (context->render_offscreen)
2090         {
2091             surface_internal_preload(context->current_rt, SRGB_RGB);
2092
2093             ENTER_GL();
2094             context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, context->current_rt, NULL, SFLAG_INTEXTURE);
2095             LEAVE_GL();
2096         }
2097         else
2098         {
2099             ENTER_GL();
2100             context_bind_fbo(context, GL_FRAMEBUFFER, NULL);
2101             LEAVE_GL();
2102         }
2103
2104         context->draw_buffer_dirty = TRUE;
2105     }
2106
2107     if (context->draw_buffer_dirty)
2108     {
2109         context_apply_draw_buffers(context, 1, &context->current_rt);
2110         if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
2111             context->draw_buffer_dirty = FALSE;
2112     }
2113
2114     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2115     {
2116         ENTER_GL();
2117         context_check_fbo_status(context, GL_FRAMEBUFFER);
2118         LEAVE_GL();
2119     }
2120
2121     SetupForBlit(device, context);
2122 }
2123
2124 static BOOL context_validate_rt_config(UINT rt_count,
2125         IWineD3DSurfaceImpl **rts, IWineD3DSurfaceImpl *ds)
2126 {
2127     unsigned int i;
2128
2129     if (ds) return TRUE;
2130
2131     for (i = 0; i < rt_count; ++i)
2132     {
2133         if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL)
2134             return TRUE;
2135     }
2136
2137     WARN("Invalid render target config, need at least one attachment.\n");
2138     return FALSE;
2139 }
2140
2141 /* Context activation is done by the caller. */
2142 BOOL context_apply_clear_state(struct wined3d_context *context, IWineD3DDeviceImpl *device,
2143         UINT rt_count, IWineD3DSurfaceImpl **rts, IWineD3DSurfaceImpl *depth_stencil)
2144 {
2145     const struct StateEntry *state_table = device->StateTable;
2146     UINT i;
2147
2148     if (!context_validate_rt_config(rt_count, rts, depth_stencil))
2149         return FALSE;
2150
2151
2152     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2153     {
2154         context_validate_onscreen_formats(device, context, depth_stencil);
2155
2156         ENTER_GL();
2157
2158         if (!rt_count || surface_is_offscreen(rts[0]))
2159         {
2160             for (i = 0; i < rt_count; ++i)
2161             {
2162                 context->blit_targets[i] = rts[i];
2163             }
2164             while (i < context->gl_info->limits.buffers)
2165             {
2166                 context->blit_targets[i] = NULL;
2167                 ++i;
2168             }
2169             context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, depth_stencil, SFLAG_INTEXTURE);
2170             glReadBuffer(GL_NONE);
2171             checkGLcall("glReadBuffer");
2172         }
2173         else
2174         {
2175             context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, SFLAG_INDRAWABLE);
2176         }
2177
2178         LEAVE_GL();
2179     }
2180
2181     context_apply_draw_buffers(context, rt_count, rts);
2182     context->draw_buffer_dirty = TRUE;
2183
2184     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2185     {
2186         ENTER_GL();
2187         context_check_fbo_status(context, GL_FRAMEBUFFER);
2188         LEAVE_GL();
2189     }
2190
2191     if (context->last_was_blit)
2192     {
2193         device->frag_pipe->enable_extension(TRUE);
2194     }
2195
2196     /* Blending and clearing should be orthogonal, but tests on the nvidia
2197      * driver show that disabling blending when clearing improves the clearing
2198      * performance incredibly. */
2199     ENTER_GL();
2200     glDisable(GL_BLEND);
2201     glEnable(GL_SCISSOR_TEST);
2202     checkGLcall("glEnable GL_SCISSOR_TEST");
2203     LEAVE_GL();
2204
2205     context->last_was_blit = FALSE;
2206     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_table);
2207     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_table);
2208     Context_MarkStateDirty(context, STATE_SCISSORRECT, state_table);
2209
2210     return TRUE;
2211 }
2212
2213 /* Context activation is done by the caller. */
2214 BOOL context_apply_draw_state(struct wined3d_context *context, IWineD3DDeviceImpl *device)
2215 {
2216     const struct StateEntry *state_table = device->StateTable;
2217     unsigned int i;
2218
2219     if (!context_validate_rt_config(context->gl_info->limits.buffers,
2220             device->render_targets, device->depth_stencil))
2221         return FALSE;
2222
2223     /* Preload resources before FBO setup. Texture preload in particular may
2224      * result in changes to the current FBO, due to using e.g. FBO blits for
2225      * updating a resource location. */
2226     IWineD3DDeviceImpl_FindTexUnitMap(device);
2227     device_preload_textures(device);
2228     if (isStateDirty(context, STATE_VDECL))
2229         device_update_stream_info(device, context->gl_info);
2230
2231     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2232     {
2233         context_validate_onscreen_formats(device, context, device->depth_stencil);
2234
2235         if (!context->render_offscreen)
2236         {
2237             ENTER_GL();
2238             context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, SFLAG_INDRAWABLE);
2239             LEAVE_GL();
2240         }
2241         else
2242         {
2243             ENTER_GL();
2244             context_apply_fbo_state(context, GL_FRAMEBUFFER, device->render_targets,
2245                     device->depth_stencil, SFLAG_INTEXTURE);
2246             glReadBuffer(GL_NONE);
2247             checkGLcall("glReadBuffer");
2248             LEAVE_GL();
2249         }
2250     }
2251
2252     if (context->draw_buffer_dirty)
2253     {
2254         context_apply_draw_buffers(context, context->gl_info->limits.buffers, device->render_targets);
2255         context->draw_buffer_dirty = FALSE;
2256     }
2257
2258     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2259     {
2260         ENTER_GL();
2261         context_check_fbo_status(context, GL_FRAMEBUFFER);
2262         LEAVE_GL();
2263     }
2264
2265     if (context->last_was_blit)
2266     {
2267         device->frag_pipe->enable_extension(TRUE);
2268     }
2269
2270     ENTER_GL();
2271     for (i = 0; i < context->numDirtyEntries; ++i)
2272     {
2273         DWORD rep = context->dirtyArray[i];
2274         DWORD idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT);
2275         BYTE shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
2276         context->isStateDirty[idx] &= ~(1 << shift);
2277         state_table[rep].apply(rep, device->stateBlock, context);
2278     }
2279     LEAVE_GL();
2280     context->numDirtyEntries = 0; /* This makes the whole list clean */
2281     context->last_was_blit = FALSE;
2282
2283     return TRUE;
2284 }
2285
2286 static void context_setup_target(IWineD3DDeviceImpl *device,
2287         struct wined3d_context *context, IWineD3DSurfaceImpl *target)
2288 {
2289     BOOL old_render_offscreen = context->render_offscreen, render_offscreen;
2290     const struct StateEntry *StateTable = device->StateTable;
2291
2292     if (!target) return;
2293     render_offscreen = surface_is_offscreen(target);
2294     if (context->current_rt == target && render_offscreen == old_render_offscreen) return;
2295
2296     /* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers
2297      * the alpha blend state changes with different render target formats. */
2298     if (!context->current_rt)
2299     {
2300         Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
2301     }
2302     else
2303     {
2304         const struct wined3d_format *old = context->current_rt->resource.format;
2305         const struct wined3d_format *new = target->resource.format;
2306
2307         if (old->id != new->id)
2308         {
2309             /* Disable blending when the alpha mask has changed and when a format doesn't support blending. */
2310             if ((old->alpha_mask && !new->alpha_mask) || (!old->alpha_mask && new->alpha_mask)
2311                     || !(new->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
2312             {
2313                 Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
2314             }
2315             /* Update sRGB writing when switching between formats that do/do not support sRGB writing */
2316             if ((old->flags & WINED3DFMT_FLAG_SRGB_WRITE) != (new->flags & WINED3DFMT_FLAG_SRGB_WRITE))
2317             {
2318                 Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), StateTable);
2319             }
2320         }
2321
2322         /* When switching away from an offscreen render target, and we're not
2323          * using FBOs, we have to read the drawable into the texture. This is
2324          * done via PreLoad (and SFLAG_INDRAWABLE set on the surface). There
2325          * are some things that need care though. PreLoad needs a GL context,
2326          * and FindContext is called before the context is activated. It also
2327          * has to be called with the old rendertarget active, otherwise a
2328          * wrong drawable is read. */
2329         if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
2330                 && old_render_offscreen && context->current_rt != target)
2331         {
2332             /* Read the back buffer of the old drawable into the destination texture. */
2333             if (context->current_rt->texture_name_srgb)
2334             {
2335                 surface_internal_preload(context->current_rt, SRGB_BOTH);
2336             }
2337             else
2338             {
2339                 surface_internal_preload(context->current_rt, SRGB_RGB);
2340             }
2341
2342             surface_modify_location(context->current_rt, SFLAG_INDRAWABLE, FALSE);
2343         }
2344     }
2345
2346     context->draw_buffer_dirty = TRUE;
2347     context->current_rt = target;
2348     context_set_render_offscreen(context, StateTable, render_offscreen);
2349 }
2350
2351 /* Do not call while under the GL lock. */
2352 struct wined3d_context *context_acquire(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *target)
2353 {
2354     struct wined3d_context *current_context = context_get_current();
2355     struct wined3d_context *context;
2356
2357     TRACE("device %p, target %p.\n", device, target);
2358
2359     context = FindContext(device, target);
2360     context_setup_target(device, context, target);
2361     context_enter(context);
2362     if (!context->valid) return context;
2363
2364     if (context != current_context)
2365     {
2366         if (!context_set_current(context)) ERR("Failed to activate the new context.\n");
2367         else device->frag_pipe->enable_extension(!context->last_was_blit);
2368
2369         if (context->vshader_const_dirty)
2370         {
2371             memset(context->vshader_const_dirty, 1,
2372                     sizeof(*context->vshader_const_dirty) * device->d3d_vshader_constantF);
2373             device->highest_dirty_vs_const = device->d3d_vshader_constantF;
2374         }
2375         if (context->pshader_const_dirty)
2376         {
2377             memset(context->pshader_const_dirty, 1,
2378                    sizeof(*context->pshader_const_dirty) * device->d3d_pshader_constantF);
2379             device->highest_dirty_ps_const = device->d3d_pshader_constantF;
2380         }
2381     }
2382     else if (context->restore_ctx)
2383     {
2384         context_set_gl_context(context);
2385     }
2386
2387     return context;
2388 }