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