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