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