wined3d: Rename the device "strided_streams" field to "stream_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->state_table = device->StateTable;
1453
1454     /* Mark all states dirty to force a proper initialization of the states
1455      * on the first use of the context. */
1456     for (state = 0; state <= STATE_HIGHEST; ++state)
1457     {
1458         if (ret->state_table[state].representative)
1459             context_invalidate_state(ret, state);
1460     }
1461
1462     ret->swapchain = swapchain;
1463     ret->current_rt = target;
1464     ret->tid = GetCurrentThreadId();
1465
1466     ret->render_offscreen = surface_is_offscreen(target);
1467     ret->draw_buffers_mask = context_generate_rt_mask(GL_BACK);
1468     ret->valid = 1;
1469
1470     ret->glCtx = ctx;
1471     ret->win_handle = swapchain->win_handle;
1472     ret->hdc = hdc;
1473     ret->pixel_format = pixel_format;
1474
1475     /* Set up the context defaults */
1476     if (!context_set_current(ret))
1477     {
1478         ERR("Cannot activate context to set up defaults.\n");
1479         device_context_remove(device, ret);
1480         context_release(ret);
1481         if (!wglDeleteContext(ctx))
1482             ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx, GetLastError());
1483         goto out;
1484     }
1485
1486     if (context_debug_output_enabled(gl_info))
1487     {
1488         GL_EXTCALL(glDebugMessageCallbackARB(wined3d_debug_callback, ret));
1489         if (TRACE_ON(d3d_synchronous))
1490             gl_info->gl_ops.gl.p_glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
1491         GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_FALSE));
1492         if (ERR_ON(d3d))
1493         {
1494             GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_ERROR_ARB,
1495                     GL_DONT_CARE, 0, NULL, GL_TRUE));
1496         }
1497         if (FIXME_ON(d3d))
1498         {
1499             GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB,
1500                     GL_DONT_CARE, 0, NULL, GL_TRUE));
1501             GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB,
1502                     GL_DONT_CARE, 0, NULL, GL_TRUE));
1503             GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_PORTABILITY_ARB,
1504                     GL_DONT_CARE, 0, NULL, GL_TRUE));
1505         }
1506         if (WARN_ON(d3d_perf))
1507         {
1508             GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_PERFORMANCE_ARB,
1509                     GL_DONT_CARE, 0, NULL, GL_TRUE));
1510         }
1511     }
1512
1513     switch (swapchain->desc.swap_interval)
1514     {
1515         case WINED3DPRESENT_INTERVAL_IMMEDIATE:
1516             swap_interval = 0;
1517             break;
1518         case WINED3DPRESENT_INTERVAL_DEFAULT:
1519         case WINED3DPRESENT_INTERVAL_ONE:
1520             swap_interval = 1;
1521             break;
1522         case WINED3DPRESENT_INTERVAL_TWO:
1523             swap_interval = 2;
1524             break;
1525         case WINED3DPRESENT_INTERVAL_THREE:
1526             swap_interval = 3;
1527             break;
1528         case WINED3DPRESENT_INTERVAL_FOUR:
1529             swap_interval = 4;
1530             break;
1531         default:
1532             FIXME("Unknown swap interval %#x.\n", swapchain->desc.swap_interval);
1533             swap_interval = 1;
1534     }
1535
1536     if (gl_info->supported[WGL_EXT_SWAP_CONTROL])
1537     {
1538         if (!GL_EXTCALL(wglSwapIntervalEXT(swap_interval)))
1539             ERR("wglSwapIntervalEXT failed to set swap interval %d for context %p, last error %#x\n",
1540                 swap_interval, ret, GetLastError());
1541     }
1542
1543     gl_info->gl_ops.gl.p_glGetIntegerv(GL_AUX_BUFFERS, &ret->aux_buffers);
1544
1545     TRACE("Setting up the screen\n");
1546
1547     gl_info->gl_ops.gl.p_glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1548     checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1549
1550     gl_info->gl_ops.gl.p_glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1551     checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1552
1553     gl_info->gl_ops.gl.p_glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1554     checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1555
1556     gl_info->gl_ops.gl.p_glPixelStorei(GL_PACK_ALIGNMENT, device->surface_alignment);
1557     checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, device->surface_alignment);");
1558     gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_ALIGNMENT, device->surface_alignment);
1559     checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, device->surface_alignment);");
1560
1561     if (gl_info->supported[APPLE_CLIENT_STORAGE])
1562     {
1563         /* Most textures will use client storage if supported. Exceptions are
1564          * non-native power of 2 textures and textures in DIB sections. */
1565         gl_info->gl_ops.gl.p_glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
1566         checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
1567     }
1568     if (gl_info->supported[ARB_VERTEX_BLEND])
1569     {
1570         /* Direct3D always uses n-1 weights for n world matrices and uses
1571          * 1 - sum for the last one this is equal to GL_WEIGHT_SUM_UNITY_ARB.
1572          * Enabling it doesn't do anything unless GL_VERTEX_BLEND_ARB isn't
1573          * enabled as well. */
1574         gl_info->gl_ops.gl.p_glEnable(GL_WEIGHT_SUM_UNITY_ARB);
1575         checkGLcall("glEnable(GL_WEIGHT_SUM_UNITY_ARB)");
1576     }
1577     if (gl_info->supported[NV_TEXTURE_SHADER2])
1578     {
1579         /* Set up the previous texture input for all shader units. This applies to bump mapping, and in d3d
1580          * the previous texture where to source the offset from is always unit - 1.
1581          */
1582         for (s = 1; s < gl_info->limits.textures; ++s)
1583         {
1584             context_active_texture(ret, gl_info, s);
1585             gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV,
1586                     GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + s - 1);
1587             checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, ...");
1588         }
1589     }
1590     if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1591     {
1592         /* MacOS(radeon X1600 at least, but most likely others too) refuses to draw if GLSL and ARBFP are
1593          * enabled, but the currently bound arbfp program is 0. Enabling ARBFP with prog 0 is invalid, but
1594          * GLSL should bypass this. This causes problems in programs that never use the fixed function pipeline,
1595          * because the ARBFP extension is enabled by the ARBFP pipeline at context creation, but no program
1596          * is ever assigned.
1597          *
1598          * So make sure a program is assigned to each context. The first real ARBFP use will set a different
1599          * program and the dummy program is destroyed when the context is destroyed.
1600          */
1601         const char *dummy_program =
1602                 "!!ARBfp1.0\n"
1603                 "MOV result.color, fragment.color.primary;\n"
1604                 "END\n";
1605         GL_EXTCALL(glGenProgramsARB(1, &ret->dummy_arbfp_prog));
1606         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ret->dummy_arbfp_prog));
1607         GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(dummy_program), dummy_program));
1608     }
1609
1610     if (gl_info->supported[ARB_POINT_SPRITE])
1611     {
1612         for (s = 0; s < gl_info->limits.textures; ++s)
1613         {
1614             context_active_texture(ret, gl_info, s);
1615             gl_info->gl_ops.gl.p_glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
1616             checkGLcall("glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)");
1617         }
1618     }
1619
1620     if (gl_info->supported[ARB_PROVOKING_VERTEX])
1621     {
1622         GL_EXTCALL(glProvokingVertex(GL_FIRST_VERTEX_CONVENTION));
1623     }
1624     else if (gl_info->supported[EXT_PROVOKING_VERTEX])
1625     {
1626         GL_EXTCALL(glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT));
1627     }
1628     ret->select_shader = 1;
1629
1630     /* If this happens to be the first context for the device, dummy textures
1631      * are not created yet. In that case, they will be created (and bound) by
1632      * create_dummy_textures right after this context is initialized. */
1633     if (device->dummy_texture_2d[0])
1634         bind_dummy_textures(device, ret);
1635
1636     TRACE("Created context %p.\n", ret);
1637
1638     return ret;
1639
1640 out:
1641     HeapFree(GetProcessHeap(), 0, ret->free_event_queries);
1642     HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries);
1643     HeapFree(GetProcessHeap(), 0, ret->draw_buffers);
1644     HeapFree(GetProcessHeap(), 0, ret->blit_targets);
1645     HeapFree(GetProcessHeap(), 0, ret);
1646     return NULL;
1647 }
1648
1649 /* Do not call while under the GL lock. */
1650 void context_destroy(struct wined3d_device *device, struct wined3d_context *context)
1651 {
1652     BOOL destroy;
1653
1654     TRACE("Destroying ctx %p\n", context);
1655
1656     if (context->tid == GetCurrentThreadId() || !context->current)
1657     {
1658         context_destroy_gl_resources(context);
1659         TlsSetValue(wined3d_context_tls_idx, NULL);
1660         destroy = TRUE;
1661     }
1662     else
1663     {
1664         /* Make a copy of gl_info for context_destroy_gl_resources use, the one
1665            in wined3d_adapter may go away in the meantime */
1666         struct wined3d_gl_info *gl_info = HeapAlloc(GetProcessHeap(), 0, sizeof(*gl_info));
1667         *gl_info = *context->gl_info;
1668         context->gl_info = gl_info;
1669         context->destroyed = 1;
1670         destroy = FALSE;
1671     }
1672
1673     HeapFree(GetProcessHeap(), 0, context->draw_buffers);
1674     HeapFree(GetProcessHeap(), 0, context->blit_targets);
1675     device_context_remove(device, context);
1676     if (destroy) HeapFree(GetProcessHeap(), 0, context);
1677 }
1678
1679 /* Context activation is done by the caller. */
1680 static void set_blit_dimension(const struct wined3d_gl_info *gl_info, UINT width, UINT height)
1681 {
1682     const GLdouble projection[] =
1683     {
1684         2.0 / width,          0.0,  0.0, 0.0,
1685                 0.0, 2.0 / height,  0.0, 0.0,
1686                 0.0,          0.0,  2.0, 0.0,
1687                -1.0,         -1.0, -1.0, 1.0,
1688     };
1689
1690     gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
1691     checkGLcall("glMatrixMode(GL_PROJECTION)");
1692     gl_info->gl_ops.gl.p_glLoadMatrixd(projection);
1693     checkGLcall("glLoadMatrixd");
1694     gl_info->gl_ops.gl.p_glViewport(0, 0, width, height);
1695     checkGLcall("glViewport");
1696 }
1697
1698 static void context_get_rt_size(const struct wined3d_context *context, SIZE *size)
1699 {
1700     const struct wined3d_surface *rt = context->current_rt;
1701
1702     if (rt->container.type == WINED3D_CONTAINER_SWAPCHAIN
1703             && rt->container.u.swapchain->front_buffer == rt)
1704     {
1705         RECT window_size;
1706
1707         GetClientRect(context->win_handle, &window_size);
1708         size->cx = window_size.right - window_size.left;
1709         size->cy = window_size.bottom - window_size.top;
1710
1711         return;
1712     }
1713
1714     size->cx = rt->resource.width;
1715     size->cy = rt->resource.height;
1716 }
1717
1718 /*****************************************************************************
1719  * SetupForBlit
1720  *
1721  * Sets up a context for DirectDraw blitting.
1722  * All texture units are disabled, texture unit 0 is set as current unit
1723  * fog, lighting, blending, alpha test, z test, scissor test, culling disabled
1724  * color writing enabled for all channels
1725  * register combiners disabled, shaders disabled
1726  * world matrix is set to identity, texture matrix 0 too
1727  * projection matrix is setup for drawing screen coordinates
1728  *
1729  * Params:
1730  *  This: Device to activate the context for
1731  *  context: Context to setup
1732  *
1733  *****************************************************************************/
1734 /* Context activation is done by the caller. */
1735 static void SetupForBlit(const struct wined3d_device *device, struct wined3d_context *context)
1736 {
1737     int i;
1738     const struct wined3d_gl_info *gl_info = context->gl_info;
1739     DWORD sampler;
1740     SIZE rt_size;
1741
1742     TRACE("Setting up context %p for blitting\n", context);
1743
1744     context_get_rt_size(context, &rt_size);
1745
1746     if (context->last_was_blit)
1747     {
1748         if (context->blit_w != rt_size.cx || context->blit_h != rt_size.cy)
1749         {
1750             set_blit_dimension(gl_info, rt_size.cx, rt_size.cy);
1751             context->blit_w = rt_size.cx;
1752             context->blit_h = rt_size.cy;
1753             /* No need to dirtify here, the states are still dirtified because
1754              * they weren't applied since the last SetupForBlit() call. */
1755         }
1756         TRACE("Context is already set up for blitting, nothing to do\n");
1757         return;
1758     }
1759     context->last_was_blit = TRUE;
1760
1761     /* Disable all textures. The caller can then bind a texture it wants to blit
1762      * from
1763      *
1764      * The blitting code uses (for now) the fixed function pipeline, so make sure to reset all fixed
1765      * function texture unit. No need to care for higher samplers
1766      */
1767     for (i = gl_info->limits.textures - 1; i > 0 ; --i)
1768     {
1769         sampler = device->rev_tex_unit_map[i];
1770         context_active_texture(context, gl_info, i);
1771
1772         if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
1773         {
1774             gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1775             checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
1776         }
1777         gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
1778         checkGLcall("glDisable GL_TEXTURE_3D");
1779         if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
1780         {
1781             gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
1782             checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
1783         }
1784         gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
1785         checkGLcall("glDisable GL_TEXTURE_2D");
1786
1787         gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1788         checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);");
1789
1790         if (sampler != WINED3D_UNMAPPED_STAGE)
1791         {
1792             if (sampler < MAX_TEXTURES)
1793                 context_invalidate_state(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP));
1794             context_invalidate_state(context, STATE_SAMPLER(sampler));
1795         }
1796     }
1797     context_active_texture(context, gl_info, 0);
1798
1799     sampler = device->rev_tex_unit_map[0];
1800
1801     if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
1802     {
1803         gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1804         checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
1805     }
1806     gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
1807     checkGLcall("glDisable GL_TEXTURE_3D");
1808     if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
1809     {
1810         gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
1811         checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
1812     }
1813     gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
1814     checkGLcall("glDisable GL_TEXTURE_2D");
1815
1816     gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1817
1818     gl_info->gl_ops.gl.p_glMatrixMode(GL_TEXTURE);
1819     checkGLcall("glMatrixMode(GL_TEXTURE)");
1820     gl_info->gl_ops.gl.p_glLoadIdentity();
1821     checkGLcall("glLoadIdentity()");
1822
1823     if (gl_info->supported[EXT_TEXTURE_LOD_BIAS])
1824     {
1825         gl_info->gl_ops.gl.p_glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
1826                 GL_TEXTURE_LOD_BIAS_EXT, 0.0f);
1827         checkGLcall("glTexEnvf GL_TEXTURE_LOD_BIAS_EXT ...");
1828     }
1829
1830     if (sampler != WINED3D_UNMAPPED_STAGE)
1831     {
1832         if (sampler < MAX_TEXTURES)
1833         {
1834             context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + sampler));
1835             context_invalidate_state(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP));
1836         }
1837         context_invalidate_state(context, STATE_SAMPLER(sampler));
1838     }
1839
1840     /* Other misc states */
1841     gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
1842     checkGLcall("glDisable(GL_ALPHA_TEST)");
1843     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHATESTENABLE));
1844     gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
1845     checkGLcall("glDisable GL_LIGHTING");
1846     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_LIGHTING));
1847     gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_TEST);
1848     checkGLcall("glDisable GL_DEPTH_TEST");
1849     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZENABLE));
1850     glDisableWINE(GL_FOG);
1851     checkGLcall("glDisable GL_FOG");
1852     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_FOGENABLE));
1853     gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
1854     checkGLcall("glDisable GL_BLEND");
1855     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE));
1856     gl_info->gl_ops.gl.p_glDisable(GL_CULL_FACE);
1857     checkGLcall("glDisable GL_CULL_FACE");
1858     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CULLMODE));
1859     gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST);
1860     checkGLcall("glDisable GL_STENCIL_TEST");
1861     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_STENCILENABLE));
1862     gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST);
1863     checkGLcall("glDisable GL_SCISSOR_TEST");
1864     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE));
1865     if (gl_info->supported[ARB_POINT_SPRITE])
1866     {
1867         gl_info->gl_ops.gl.p_glDisable(GL_POINT_SPRITE_ARB);
1868         checkGLcall("glDisable GL_POINT_SPRITE_ARB");
1869         context_invalidate_state(context, STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE));
1870     }
1871     gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE,GL_TRUE,GL_TRUE);
1872     checkGLcall("glColorMask");
1873     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE));
1874     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1));
1875     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2));
1876     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3));
1877     if (gl_info->supported[EXT_SECONDARY_COLOR])
1878     {
1879         gl_info->gl_ops.gl.p_glDisable(GL_COLOR_SUM_EXT);
1880         context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SPECULARENABLE));
1881         checkGLcall("glDisable(GL_COLOR_SUM_EXT)");
1882     }
1883
1884     /* Setup transforms */
1885     gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
1886     checkGLcall("glMatrixMode(GL_MODELVIEW)");
1887     gl_info->gl_ops.gl.p_glLoadIdentity();
1888     checkGLcall("glLoadIdentity()");
1889     context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)));
1890
1891     context->last_was_rhw = TRUE;
1892     context_invalidate_state(context, STATE_VDECL); /* because of last_was_rhw = TRUE */
1893
1894     gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)");
1895     gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)");
1896     gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)");
1897     gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)");
1898     gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)");
1899     gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)");
1900     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CLIPPING));
1901
1902     set_blit_dimension(gl_info, rt_size.cx, rt_size.cy);
1903
1904     /* Disable shaders */
1905     device->shader_backend->shader_select(context, WINED3D_SHADER_MODE_NONE, WINED3D_SHADER_MODE_NONE);
1906     context->select_shader = 1;
1907     context->load_constants = 1;
1908
1909     context->blit_w = rt_size.cx;
1910     context->blit_h = rt_size.cy;
1911     context_invalidate_state(context, STATE_VIEWPORT);
1912     context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
1913 }
1914
1915 static inline BOOL is_rt_mask_onscreen(DWORD rt_mask)
1916 {
1917     return rt_mask & (1 << 31);
1918 }
1919
1920 static inline GLenum draw_buffer_from_rt_mask(DWORD rt_mask)
1921 {
1922     return rt_mask & ~(1 << 31);
1923 }
1924
1925 /* Context activation is done by the caller. */
1926 static void context_apply_draw_buffers(struct wined3d_context *context, DWORD rt_mask)
1927 {
1928     const struct wined3d_gl_info *gl_info = context->gl_info;
1929
1930     if (!rt_mask)
1931     {
1932         gl_info->gl_ops.gl.p_glDrawBuffer(GL_NONE);
1933         checkGLcall("glDrawBuffer()");
1934     }
1935     else if (is_rt_mask_onscreen(rt_mask))
1936     {
1937         gl_info->gl_ops.gl.p_glDrawBuffer(draw_buffer_from_rt_mask(rt_mask));
1938         checkGLcall("glDrawBuffer()");
1939     }
1940     else
1941     {
1942         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
1943         {
1944             unsigned int i = 0;
1945
1946             while (rt_mask)
1947             {
1948                 if (rt_mask & 1)
1949                     context->draw_buffers[i] = GL_COLOR_ATTACHMENT0 + i;
1950                 else
1951                     context->draw_buffers[i] = GL_NONE;
1952
1953                 rt_mask >>= 1;
1954                 ++i;
1955             }
1956
1957             if (gl_info->supported[ARB_DRAW_BUFFERS])
1958             {
1959                 GL_EXTCALL(glDrawBuffersARB(i, context->draw_buffers));
1960                 checkGLcall("glDrawBuffers()");
1961             }
1962             else
1963             {
1964                 gl_info->gl_ops.gl.p_glDrawBuffer(context->draw_buffers[0]);
1965                 checkGLcall("glDrawBuffer()");
1966             }
1967         }
1968         else
1969         {
1970             ERR("Unexpected draw buffers mask with backbuffer ORM.\n");
1971         }
1972     }
1973 }
1974
1975 /* Context activation is done by the caller. */
1976 void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer)
1977 {
1978     const struct wined3d_gl_info *gl_info = context->gl_info;
1979     DWORD *current_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
1980     DWORD new_mask = context_generate_rt_mask(buffer);
1981
1982     if (new_mask == *current_mask)
1983         return;
1984
1985     gl_info->gl_ops.gl.p_glDrawBuffer(buffer);
1986     checkGLcall("glDrawBuffer()");
1987
1988     *current_mask = new_mask;
1989 }
1990
1991 /* Context activation is done by the caller. */
1992 void context_active_texture(struct wined3d_context *context, const struct wined3d_gl_info *gl_info, unsigned int unit)
1993 {
1994     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0 + unit));
1995     checkGLcall("glActiveTextureARB");
1996     context->active_texture = unit;
1997 }
1998
1999 void context_bind_texture(struct wined3d_context *context, GLenum target, GLuint name)
2000 {
2001     const struct wined3d_gl_info *gl_info = context->gl_info;
2002     DWORD unit = context->active_texture;
2003     DWORD old_texture_type = context->texture_type[unit];
2004
2005     if (name)
2006     {
2007         gl_info->gl_ops.gl.p_glBindTexture(target, name);
2008         checkGLcall("glBindTexture");
2009     }
2010     else
2011     {
2012         target = GL_NONE;
2013     }
2014
2015     if (old_texture_type != target)
2016     {
2017         const struct wined3d_device *device = context->swapchain->device;
2018
2019         switch (old_texture_type)
2020         {
2021             case GL_NONE:
2022                 /* nothing to do */
2023                 break;
2024             case GL_TEXTURE_2D:
2025                 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, device->dummy_texture_2d[unit]);
2026                 checkGLcall("glBindTexture");
2027                 break;
2028             case GL_TEXTURE_RECTANGLE_ARB:
2029                 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_RECTANGLE_ARB, device->dummy_texture_rect[unit]);
2030                 checkGLcall("glBindTexture");
2031                 break;
2032             case GL_TEXTURE_CUBE_MAP:
2033                 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP, device->dummy_texture_cube[unit]);
2034                 checkGLcall("glBindTexture");
2035                 break;
2036             case GL_TEXTURE_3D:
2037                 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_3D, device->dummy_texture_3d[unit]);
2038                 checkGLcall("glBindTexture");
2039                 break;
2040             default:
2041                 ERR("Unexpected texture target %#x\n", old_texture_type);
2042         }
2043
2044         context->texture_type[unit] = target;
2045     }
2046 }
2047
2048 static void context_set_render_offscreen(struct wined3d_context *context, BOOL offscreen)
2049 {
2050     if (context->render_offscreen == offscreen) return;
2051
2052     context_invalidate_state(context, STATE_POINTSPRITECOORDORIGIN);
2053     context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
2054     context_invalidate_state(context, STATE_VIEWPORT);
2055     context_invalidate_state(context, STATE_SCISSORRECT);
2056     context_invalidate_state(context, STATE_FRONTFACE);
2057     context->render_offscreen = offscreen;
2058 }
2059
2060 static BOOL match_depth_stencil_format(const struct wined3d_format *existing,
2061         const struct wined3d_format *required)
2062 {
2063     BYTE existing_depth, existing_stencil, required_depth, required_stencil;
2064
2065     if (existing == required) return TRUE;
2066     if ((existing->flags & WINED3DFMT_FLAG_FLOAT) != (required->flags & WINED3DFMT_FLAG_FLOAT)) return FALSE;
2067
2068     getDepthStencilBits(existing, &existing_depth, &existing_stencil);
2069     getDepthStencilBits(required, &required_depth, &required_stencil);
2070
2071     if(existing_depth < required_depth) return FALSE;
2072     /* If stencil bits are used the exact amount is required - otherwise wrapping
2073      * won't work correctly */
2074     if(required_stencil && required_stencil != existing_stencil) return FALSE;
2075     return TRUE;
2076 }
2077
2078 /* The caller provides a context */
2079 static void context_validate_onscreen_formats(struct wined3d_context *context,
2080         const struct wined3d_surface *depth_stencil)
2081 {
2082     /* Onscreen surfaces are always in a swapchain */
2083     struct wined3d_swapchain *swapchain = context->current_rt->container.u.swapchain;
2084
2085     if (context->render_offscreen || !depth_stencil) return;
2086     if (match_depth_stencil_format(swapchain->ds_format, depth_stencil->resource.format)) return;
2087
2088     /* TODO: If the requested format would satisfy the needs of the existing one(reverse match),
2089      * or no onscreen depth buffer was created, the OpenGL drawable could be changed to the new
2090      * format. */
2091     WARN("Depth stencil format is not supported by WGL, rendering the backbuffer in an FBO\n");
2092
2093     /* The currently active context is the necessary context to access the swapchain's onscreen buffers */
2094     surface_load_location(context->current_rt, SFLAG_INTEXTURE, NULL);
2095     swapchain->render_to_fbo = TRUE;
2096     swapchain_update_draw_bindings(swapchain);
2097     context_set_render_offscreen(context, TRUE);
2098 }
2099
2100 static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_device *device, const struct wined3d_surface *rt)
2101 {
2102     if (!rt || rt->resource.format->id == WINED3DFMT_NULL)
2103         return 0;
2104     else if (rt->container.type == WINED3D_CONTAINER_SWAPCHAIN)
2105         return context_generate_rt_mask_from_surface(rt);
2106     else
2107         return context_generate_rt_mask(device->offscreenBuffer);
2108 }
2109
2110 /* Context activation is done by the caller. */
2111 void context_apply_blit_state(struct wined3d_context *context, const struct wined3d_device *device)
2112 {
2113     struct wined3d_surface *rt = context->current_rt;
2114     DWORD rt_mask, *cur_mask;
2115
2116     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2117     {
2118         context_validate_onscreen_formats(context, NULL);
2119
2120         if (context->render_offscreen)
2121         {
2122             surface_internal_preload(rt, SRGB_RGB);
2123
2124             context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, rt, NULL, rt->draw_binding);
2125             if (rt->resource.format->id != WINED3DFMT_NULL)
2126                 rt_mask = 1;
2127             else
2128                 rt_mask = 0;
2129         }
2130         else
2131         {
2132             context_bind_fbo(context, GL_FRAMEBUFFER, NULL);
2133             rt_mask = context_generate_rt_mask_from_surface(rt);
2134         }
2135     }
2136     else
2137     {
2138         rt_mask = context_generate_rt_mask_no_fbo(device, rt);
2139     }
2140
2141     cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
2142
2143     if (rt_mask != *cur_mask)
2144     {
2145         context_apply_draw_buffers(context, rt_mask);
2146         *cur_mask = rt_mask;
2147     }
2148
2149     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2150     {
2151         context_check_fbo_status(context, GL_FRAMEBUFFER);
2152     }
2153
2154     SetupForBlit(device, context);
2155     context_invalidate_state(context, STATE_FRAMEBUFFER);
2156 }
2157
2158 static BOOL context_validate_rt_config(UINT rt_count,
2159         struct wined3d_surface * const *rts, const struct wined3d_surface *ds)
2160 {
2161     unsigned int i;
2162
2163     if (ds) return TRUE;
2164
2165     for (i = 0; i < rt_count; ++i)
2166     {
2167         if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL)
2168             return TRUE;
2169     }
2170
2171     WARN("Invalid render target config, need at least one attachment.\n");
2172     return FALSE;
2173 }
2174
2175 /* Context activation is done by the caller. */
2176 BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_device *device,
2177         UINT rt_count, const struct wined3d_fb_state *fb)
2178 {
2179     const struct wined3d_gl_info *gl_info = context->gl_info;
2180     DWORD rt_mask = 0, *cur_mask;
2181     UINT i;
2182     struct wined3d_surface **rts = fb->render_targets;
2183
2184     if (isStateDirty(context, STATE_FRAMEBUFFER) || fb != &device->fb
2185             || rt_count != context->gl_info->limits.buffers)
2186     {
2187         if (!context_validate_rt_config(rt_count, rts, fb->depth_stencil))
2188             return FALSE;
2189
2190         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2191         {
2192             context_validate_onscreen_formats(context, fb->depth_stencil);
2193
2194             if (!rt_count || surface_is_offscreen(rts[0]))
2195             {
2196                 for (i = 0; i < rt_count; ++i)
2197                 {
2198                     context->blit_targets[i] = rts[i];
2199                     if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL)
2200                         rt_mask |= (1 << i);
2201                 }
2202                 while (i < context->gl_info->limits.buffers)
2203                 {
2204                     context->blit_targets[i] = NULL;
2205                     ++i;
2206                 }
2207                 context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, fb->depth_stencil,
2208                         rt_count ? rts[0]->draw_binding : SFLAG_INTEXTURE);
2209                 gl_info->gl_ops.gl.p_glReadBuffer(GL_NONE);
2210                 checkGLcall("glReadBuffer");
2211             }
2212             else
2213             {
2214                 context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, SFLAG_INDRAWABLE);
2215                 rt_mask = context_generate_rt_mask_from_surface(rts[0]);
2216             }
2217
2218             /* If the framebuffer is not the device's fb the device's fb has to be reapplied
2219              * next draw. Otherwise we could mark the framebuffer state clean here, once the
2220              * state management allows this */
2221             context_invalidate_state(context, STATE_FRAMEBUFFER);
2222         }
2223         else
2224         {
2225             rt_mask = context_generate_rt_mask_no_fbo(device, rt_count ? rts[0] : NULL);
2226         }
2227     }
2228     else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO
2229             && (!rt_count || surface_is_offscreen(rts[0])))
2230     {
2231         for (i = 0; i < rt_count; ++i)
2232         {
2233             if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL) rt_mask |= (1 << i);
2234         }
2235     }
2236     else
2237     {
2238         rt_mask = context_generate_rt_mask_no_fbo(device, rt_count ? rts[0] : NULL);
2239     }
2240
2241     cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
2242
2243     if (rt_mask != *cur_mask)
2244     {
2245         context_apply_draw_buffers(context, rt_mask);
2246         *cur_mask = rt_mask;
2247         context_invalidate_state(context, STATE_FRAMEBUFFER);
2248     }
2249
2250     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2251     {
2252         context_check_fbo_status(context, GL_FRAMEBUFFER);
2253     }
2254
2255     if (context->last_was_blit)
2256         context->last_was_blit = FALSE;
2257
2258     /* Blending and clearing should be orthogonal, but tests on the nvidia
2259      * driver show that disabling blending when clearing improves the clearing
2260      * performance incredibly. */
2261     gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
2262     gl_info->gl_ops.gl.p_glEnable(GL_SCISSOR_TEST);
2263     checkGLcall("glEnable GL_SCISSOR_TEST");
2264
2265     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE));
2266     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE));
2267     context_invalidate_state(context, STATE_SCISSORRECT);
2268
2269     return TRUE;
2270 }
2271
2272 static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const struct wined3d_device *device)
2273 {
2274     const struct wined3d_state *state = &device->stateBlock->state;
2275     struct wined3d_surface **rts = state->fb->render_targets;
2276     struct wined3d_shader *ps = state->pixel_shader;
2277     DWORD rt_mask, rt_mask_bits;
2278     unsigned int i;
2279
2280     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return context_generate_rt_mask_no_fbo(device, rts[0]);
2281     else if (!context->render_offscreen) return context_generate_rt_mask_from_surface(rts[0]);
2282
2283     rt_mask = ps ? ps->reg_maps.rt_mask : 1;
2284     rt_mask &= device->valid_rt_mask;
2285     rt_mask_bits = rt_mask;
2286     i = 0;
2287     while (rt_mask_bits)
2288     {
2289         rt_mask_bits &= ~(1 << i);
2290         if (!rts[i] || rts[i]->resource.format->id == WINED3DFMT_NULL)
2291             rt_mask &= ~(1 << i);
2292
2293         i++;
2294     }
2295
2296     return rt_mask;
2297 }
2298
2299 /* Context activation is done by the caller. */
2300 void context_state_fb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
2301 {
2302     const struct wined3d_device *device = context->swapchain->device;
2303     const struct wined3d_gl_info *gl_info = context->gl_info;
2304     const struct wined3d_fb_state *fb = state->fb;
2305     DWORD rt_mask = find_draw_buffers_mask(context, device);
2306     DWORD *cur_mask;
2307
2308     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2309     {
2310         if (!context->render_offscreen)
2311         {
2312             context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, SFLAG_INDRAWABLE);
2313         }
2314         else
2315         {
2316             context_apply_fbo_state(context, GL_FRAMEBUFFER, fb->render_targets, fb->depth_stencil,
2317                     fb->render_targets[0]->draw_binding);
2318             gl_info->gl_ops.gl.p_glReadBuffer(GL_NONE);
2319             checkGLcall("glReadBuffer");
2320         }
2321     }
2322
2323     cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
2324     if (rt_mask != *cur_mask)
2325     {
2326         context_apply_draw_buffers(context, rt_mask);
2327         *cur_mask = rt_mask;
2328     }
2329 }
2330
2331 /* Context activation is done by the caller. */
2332 void context_state_drawbuf(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
2333 {
2334     const struct wined3d_device *device = context->swapchain->device;
2335     DWORD rt_mask, *cur_mask;
2336
2337     if (isStateDirty(context, STATE_FRAMEBUFFER)) return;
2338
2339     cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
2340     rt_mask = find_draw_buffers_mask(context, device);
2341     if (rt_mask != *cur_mask)
2342     {
2343         context_apply_draw_buffers(context, rt_mask);
2344         *cur_mask = rt_mask;
2345     }
2346 }
2347
2348 /* Context activation is done by the caller. */
2349 BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_device *device)
2350 {
2351     const struct wined3d_state *state = &device->stateBlock->state;
2352     const struct StateEntry *state_table = context->state_table;
2353     const struct wined3d_fb_state *fb = state->fb;
2354     unsigned int i;
2355
2356     if (!context_validate_rt_config(context->gl_info->limits.buffers,
2357             fb->render_targets, fb->depth_stencil))
2358         return FALSE;
2359
2360     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && isStateDirty(context, STATE_FRAMEBUFFER))
2361     {
2362         context_validate_onscreen_formats(context, fb->depth_stencil);
2363     }
2364
2365     /* Preload resources before FBO setup. Texture preload in particular may
2366      * result in changes to the current FBO, due to using e.g. FBO blits for
2367      * updating a resource location. */
2368     device_update_tex_unit_map(device);
2369     device_preload_textures(device);
2370     if (isStateDirty(context, STATE_VDECL) || isStateDirty(context, STATE_STREAMSRC))
2371         device_update_stream_info(device, context->gl_info);
2372     if (state->index_buffer)
2373     {
2374         if (device->stream_info.all_vbo)
2375             wined3d_buffer_preload(state->index_buffer);
2376         else
2377             buffer_get_sysmem(state->index_buffer, context->gl_info);
2378     }
2379
2380     for (i = 0; i < context->numDirtyEntries; ++i)
2381     {
2382         DWORD rep = context->dirtyArray[i];
2383         DWORD idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT);
2384         BYTE shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
2385         context->isStateDirty[idx] &= ~(1 << shift);
2386         state_table[rep].apply(context, state, rep);
2387     }
2388
2389     if (context->select_shader)
2390     {
2391         device->shader_backend->shader_select(context,
2392                 use_vs(state) ? WINED3D_SHADER_MODE_SHADER : WINED3D_SHADER_MODE_FFP,
2393                 use_ps(state) ? WINED3D_SHADER_MODE_SHADER : WINED3D_SHADER_MODE_FFP);
2394         context->select_shader = 0;
2395     }
2396
2397     if (context->load_constants)
2398     {
2399         device->shader_backend->shader_load_constants(context, use_ps(state), use_vs(state));
2400         context->load_constants = 0;
2401     }
2402
2403     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2404     {
2405         context_check_fbo_status(context, GL_FRAMEBUFFER);
2406     }
2407
2408     context->numDirtyEntries = 0; /* This makes the whole list clean */
2409     context->last_was_blit = FALSE;
2410
2411     return TRUE;
2412 }
2413
2414 static void context_setup_target(struct wined3d_context *context, struct wined3d_surface *target)
2415 {
2416     BOOL old_render_offscreen = context->render_offscreen, render_offscreen;
2417
2418     render_offscreen = surface_is_offscreen(target);
2419     if (context->current_rt == target && render_offscreen == old_render_offscreen) return;
2420
2421     /* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers
2422      * the alpha blend state changes with different render target formats. */
2423     if (!context->current_rt)
2424     {
2425         context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE));
2426     }
2427     else
2428     {
2429         const struct wined3d_format *old = context->current_rt->resource.format;
2430         const struct wined3d_format *new = target->resource.format;
2431
2432         if (old->id != new->id)
2433         {
2434             /* Disable blending when the alpha mask has changed and when a format doesn't support blending. */
2435             if ((old->alpha_size && !new->alpha_size) || (!old->alpha_size && new->alpha_size)
2436                     || !(new->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
2437                 context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE));
2438
2439             /* Update sRGB writing when switching between formats that do/do not support sRGB writing */
2440             if ((old->flags & WINED3DFMT_FLAG_SRGB_WRITE) != (new->flags & WINED3DFMT_FLAG_SRGB_WRITE))
2441                 context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE));
2442         }
2443
2444         /* When switching away from an offscreen render target, and we're not
2445          * using FBOs, we have to read the drawable into the texture. This is
2446          * done via PreLoad (and SFLAG_INDRAWABLE set on the surface). There
2447          * are some things that need care though. PreLoad needs a GL context,
2448          * and FindContext is called before the context is activated. It also
2449          * has to be called with the old rendertarget active, otherwise a
2450          * wrong drawable is read. */
2451         if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
2452                 && old_render_offscreen && context->current_rt != target)
2453         {
2454             /* Read the back buffer of the old drawable into the destination texture. */
2455             if (context->current_rt->texture_name_srgb)
2456                 surface_internal_preload(context->current_rt, SRGB_SRGB);
2457             surface_internal_preload(context->current_rt, SRGB_RGB);
2458             surface_modify_location(context->current_rt, SFLAG_INDRAWABLE, FALSE);
2459         }
2460     }
2461
2462     context->current_rt = target;
2463     context_set_render_offscreen(context, render_offscreen);
2464 }
2465
2466 /* Do not call while under the GL lock. */
2467 struct wined3d_context *context_acquire(const struct wined3d_device *device, struct wined3d_surface *target)
2468 {
2469     struct wined3d_context *current_context = context_get_current();
2470     struct wined3d_context *context;
2471
2472     TRACE("device %p, target %p.\n", device, target);
2473
2474     if (current_context && current_context->destroyed)
2475         current_context = NULL;
2476
2477     if (!target)
2478     {
2479         if (current_context
2480                 && current_context->current_rt
2481                 && current_context->swapchain->device == device)
2482         {
2483             target = current_context->current_rt;
2484         }
2485         else
2486         {
2487             struct wined3d_swapchain *swapchain = device->swapchains[0];
2488             if (swapchain->back_buffers)
2489                 target = swapchain->back_buffers[0];
2490             else
2491                 target = swapchain->front_buffer;
2492         }
2493     }
2494
2495     if (current_context && current_context->current_rt == target)
2496     {
2497         context = current_context;
2498     }
2499     else if (target->container.type == WINED3D_CONTAINER_SWAPCHAIN)
2500     {
2501         TRACE("Rendering onscreen.\n");
2502
2503         context = swapchain_get_context(target->container.u.swapchain);
2504     }
2505     else
2506     {
2507         TRACE("Rendering offscreen.\n");
2508
2509         /* Stay with the current context if possible. Otherwise use the
2510          * context for the primary swapchain. */
2511         if (current_context && current_context->swapchain->device == device)
2512             context = current_context;
2513         else
2514             context = swapchain_get_context(device->swapchains[0]);
2515     }
2516
2517     context_update_window(context);
2518     context_setup_target(context, target);
2519     context_enter(context);
2520     if (!context->valid) return context;
2521
2522     if (context != current_context)
2523     {
2524         if (!context_set_current(context))
2525             ERR("Failed to activate the new context.\n");
2526     }
2527     else if (context->restore_ctx)
2528     {
2529         context_set_gl_context(context);
2530     }
2531
2532     return context;
2533 }