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