ReactOS  0.4.14-dev-49-gfb4591c
device.c
Go to the documentation of this file.
1 /*
2  * Copyright 2002 Lionel Ulmer
3  * Copyright 2002-2005 Jason Edmeades
4  * Copyright 2003-2004 Raphael Junqueira
5  * Copyright 2004 Christian Costa
6  * Copyright 2005 Oliver Stieber
7  * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
8  * Copyright 2006-2008 Henri Verbeet
9  * Copyright 2007 Andrew Riedi
10  * Copyright 2009-2011 Henri Verbeet for CodeWeavers
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 #include "config.h"
28 #include "wine/port.h"
29 
30 #include <stdio.h>
31 #ifdef HAVE_FLOAT_H
32 # include <float.h>
33 #endif
34 
35 #include "wined3d_private.h"
36 
39 
40 /* Define the default light parameters as specified by MSDN. */
42 {
43  WINED3D_LIGHT_DIRECTIONAL, /* Type */
44  { 1.0f, 1.0f, 1.0f, 0.0f }, /* Diffuse r,g,b,a */
45  { 0.0f, 0.0f, 0.0f, 0.0f }, /* Specular r,g,b,a */
46  { 0.0f, 0.0f, 0.0f, 0.0f }, /* Ambient r,g,b,a, */
47  { 0.0f, 0.0f, 0.0f }, /* Position x,y,z */
48  { 0.0f, 0.0f, 1.0f }, /* Direction x,y,z */
49  0.0f, /* Range */
50  0.0f, /* Falloff */
51  0.0f, 0.0f, 0.0f, /* Attenuation 0,1,2 */
52  0.0f, /* Theta */
53  0.0f /* Phi */
54 };
55 
56 /* Note that except for WINED3DPT_POINTLIST and WINED3DPT_LINELIST these
57  * actually have the same values in GL and D3D. */
59 {
60  switch (primitive_type)
61  {
63  return GL_POINTS;
64 
66  return GL_LINES;
67 
69  return GL_LINE_STRIP;
70 
72  return GL_TRIANGLES;
73 
75  return GL_TRIANGLE_STRIP;
76 
78  return GL_TRIANGLE_FAN;
79 
82 
85 
88 
91 
92  case WINED3D_PT_PATCH:
93  return GL_PATCHES;
94 
95  default:
96  FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type));
98  return ~0u;
99  }
100 }
101 
103 {
104  switch (primitive_type)
105  {
106  case GL_POINTS:
107  return WINED3D_PT_POINTLIST;
108 
109  case GL_LINES:
110  return WINED3D_PT_LINELIST;
111 
112  case GL_LINE_STRIP:
113  return WINED3D_PT_LINESTRIP;
114 
115  case GL_TRIANGLES:
117 
118  case GL_TRIANGLE_STRIP:
120 
121  case GL_TRIANGLE_FAN:
122  return WINED3D_PT_TRIANGLEFAN;
123 
126 
129 
132 
135 
136  case GL_PATCHES:
137  return WINED3D_PT_PATCH;
138 
139  default:
140  FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type));
141  case ~0u:
142  return WINED3D_PT_UNDEFINED;
143  }
144 }
145 
147 {
148  struct wined3d_context **new_array;
149 
150  TRACE("Adding context %p.\n", context);
151 
152  if (!(new_array = heap_realloc(device->contexts, sizeof(*new_array) * (device->context_count + 1))))
153  {
154  ERR("Failed to grow the context array.\n");
155  return FALSE;
156  }
157 
158  new_array[device->context_count++] = context;
159  device->contexts = new_array;
160  return TRUE;
161 }
162 
164 {
165  struct wined3d_context **new_array;
166  BOOL found = FALSE;
167  UINT i;
168 
169  TRACE("Removing context %p.\n", context);
170 
171  for (i = 0; i < device->context_count; ++i)
172  {
173  if (device->contexts[i] == context)
174  {
175  found = TRUE;
176  break;
177  }
178  }
179 
180  if (!found)
181  {
182  ERR("Context %p doesn't exist in context array.\n", context);
183  return;
184  }
185 
186  if (!--device->context_count)
187  {
188  heap_free(device->contexts);
189  device->contexts = NULL;
190  return;
191  }
192 
193  memmove(&device->contexts[i], &device->contexts[i + 1], (device->context_count - i) * sizeof(*device->contexts));
194  if (!(new_array = heap_realloc(device->contexts, device->context_count * sizeof(*device->contexts))))
195  {
196  ERR("Failed to shrink context array. Oh well.\n");
197  return;
198  }
199 
200  device->contexts = new_array;
201 }
202 
203 static BOOL is_full_clear(const struct wined3d_texture *texture, unsigned int sub_resource_idx,
204  const RECT *draw_rect, const RECT *clear_rect)
205 {
206  unsigned int width, height, level;
207 
208  level = sub_resource_idx % texture->level_count;
211 
212  /* partial draw rect */
213  if (draw_rect->left || draw_rect->top || draw_rect->right < width || draw_rect->bottom < height)
214  return FALSE;
215 
216  /* partial clear rect */
217  if (clear_rect && (clear_rect->left > 0 || clear_rect->top > 0
218  || clear_rect->right < width || clear_rect->bottom < height))
219  return FALSE;
220 
221  return TRUE;
222 }
223 
224 void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, const struct wined3d_fb_state *fb,
225  UINT rect_count, const RECT *clear_rect, const RECT *draw_rect, DWORD flags, const struct wined3d_color *color,
226  float depth, DWORD stencil)
227 {
228  struct wined3d_rendertarget_view *rtv = rt_count ? fb->render_targets[0] : NULL;
230  struct wined3d_rendertarget_view *dsv = fb->depth_stencil;
231  struct wined3d_surface *depth_stencil = dsv ? wined3d_rendertarget_view_get_surface(dsv) : NULL;
232  const struct wined3d_state *state = &device->cs->state;
233  const struct wined3d_gl_info *gl_info;
234  UINT drawable_width, drawable_height;
235  struct wined3d_color corrected_color;
236  struct wined3d_context *context;
237  GLbitfield clear_mask = 0;
239  unsigned int i;
240 
241  if (target)
243  else
245  if (!context->valid)
246  {
248  WARN("Invalid context, skipping clear.\n");
249  return;
250  }
251  gl_info = context->gl_info;
252 
253  /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
254  * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
255  * for the cleared parts, and the untouched parts.
256  *
257  * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
258  * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
259  * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
260  * checking all this if the dest surface is in the drawable anyway. */
261  for (i = 0; i < rt_count; ++i)
262  {
263  struct wined3d_rendertarget_view *rtv = fb->render_targets[i];
264 
265  if (rtv && rtv->format->id != WINED3DFMT_NULL)
266  {
268 
270  draw_rect, rect_count ? clear_rect : NULL))
271  wined3d_texture_load_location(rt, rtv->sub_resource_idx, context, rtv->resource->draw_binding);
272  else
273  wined3d_texture_prepare_location(rt, rtv->sub_resource_idx, context, rtv->resource->draw_binding);
274  }
275  }
276 
277  if (target)
278  {
279  render_offscreen = context->render_offscreen;
280  wined3d_rendertarget_view_get_drawable_size(rtv, context, &drawable_width, &drawable_height);
281  }
282  else
283  {
284  unsigned int ds_level = dsv->sub_resource_idx % depth_stencil->container->level_count;
285 
286  render_offscreen = TRUE;
287  drawable_width = wined3d_texture_get_level_pow2_width(depth_stencil->container, ds_level);
288  drawable_height = wined3d_texture_get_level_pow2_height(depth_stencil->container, ds_level);
289  }
290 
291  if (depth_stencil)
292  {
293  DWORD ds_location = render_offscreen ? dsv->resource->draw_binding : WINED3D_LOCATION_DRAWABLE;
295 
297  && !is_full_clear(ds, dsv->sub_resource_idx, draw_rect, rect_count ? clear_rect : NULL))
299  else
301 
303  {
306  }
307  }
308 
309  if (!context_apply_clear_state(context, state, rt_count, fb))
310  {
312  WARN("Failed to apply clear state, skipping clear.\n");
313  return;
314  }
315 
316  /* Only set the values up once, as they are not changing. */
318  {
319  if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
320  {
321  gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
323  }
324  gl_info->gl_ops.gl.p_glStencilMask(~0U);
326  gl_info->gl_ops.gl.p_glClearStencil(stencil);
327  checkGLcall("glClearStencil");
328  clear_mask = clear_mask | GL_STENCIL_BUFFER_BIT;
329  }
330 
332  {
333  gl_info->gl_ops.gl.p_glDepthMask(GL_TRUE);
335  gl_info->gl_ops.gl.p_glClearDepth(depth);
336  checkGLcall("glClearDepth");
337  clear_mask = clear_mask | GL_DEPTH_BUFFER_BIT;
338  }
339 
341  {
342  for (i = 0; i < rt_count; ++i)
343  {
344  struct wined3d_rendertarget_view *rtv = fb->render_targets[i];
345  struct wined3d_texture *texture;
346 
347  if (!rtv)
348  continue;
349 
350  if (rtv->resource->type == WINED3D_RTYPE_BUFFER)
351  {
352  FIXME("Not supported on buffer resources.\n");
353  continue;
354  }
355 
359  }
360 
362  {
363  if (rt_count > 1)
364  WARN("Clearing multiple sRGB render targets with no GL_ARB_framebuffer_sRGB "
365  "support, this might cause graphical issues.\n");
366 
367  corrected_color.r = color->r < wined3d_srgb_const1[0]
368  ? color->r * wined3d_srgb_const0[3]
370  - wined3d_srgb_const0[2];
371  corrected_color.r = min(max(corrected_color.r, 0.0f), 1.0f);
372  corrected_color.g = color->g < wined3d_srgb_const1[0]
373  ? color->g * wined3d_srgb_const0[3]
375  - wined3d_srgb_const0[2];
376  corrected_color.g = min(max(corrected_color.g, 0.0f), 1.0f);
377  corrected_color.b = color->b < wined3d_srgb_const1[0]
378  ? color->b * wined3d_srgb_const0[3]
380  - wined3d_srgb_const0[2];
381  corrected_color.b = min(max(corrected_color.b, 0.0f), 1.0f);
382  color = &corrected_color;
383  }
384 
385  gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
386  for (i = 0; i < MAX_RENDER_TARGETS; ++i)
388  gl_info->gl_ops.gl.p_glClearColor(color->r, color->g, color->b, color->a);
389  checkGLcall("glClearColor");
390  clear_mask = clear_mask | GL_COLOR_BUFFER_BIT;
391  }
392 
393  if (!rect_count)
394  {
395  if (render_offscreen)
396  {
397  gl_info->gl_ops.gl.p_glScissor(draw_rect->left, draw_rect->top,
398  draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
399  }
400  else
401  {
402  gl_info->gl_ops.gl.p_glScissor(draw_rect->left, drawable_height - draw_rect->bottom,
403  draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
404  }
405  checkGLcall("glScissor");
406  gl_info->gl_ops.gl.p_glClear(clear_mask);
407  checkGLcall("glClear");
408  }
409  else
410  {
411  RECT current_rect;
412 
413  /* Now process each rect in turn. */
414  for (i = 0; i < rect_count; ++i)
415  {
416  /* Note that GL uses lower left, width/height. */
417  IntersectRect(&current_rect, draw_rect, &clear_rect[i]);
418 
419  TRACE("clear_rect[%u] %s, current_rect %s.\n", i,
420  wine_dbgstr_rect(&clear_rect[i]),
421  wine_dbgstr_rect(&current_rect));
422 
423  /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
424  * The rectangle is not cleared, no error is returned, but further rectangles are
425  * still cleared if they are valid. */
426  if (current_rect.left > current_rect.right || current_rect.top > current_rect.bottom)
427  {
428  TRACE("Rectangle with negative dimensions, ignoring.\n");
429  continue;
430  }
431 
432  if (render_offscreen)
433  {
434  gl_info->gl_ops.gl.p_glScissor(current_rect.left, current_rect.top,
435  current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
436  }
437  else
438  {
439  gl_info->gl_ops.gl.p_glScissor(current_rect.left, drawable_height - current_rect.bottom,
440  current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
441  }
442  checkGLcall("glScissor");
443 
444  gl_info->gl_ops.gl.p_glClear(clear_mask);
445  checkGLcall("glClear");
446  }
447  }
448 
450  && target->container->swapchain && target->container->swapchain->front_buffer == target->container))
451  gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
452 
454 }
455 
457 {
458  ULONG refcount = InterlockedIncrement(&device->ref);
459 
460  TRACE("%p increasing refcount to %u.\n", device, refcount);
461 
462  return refcount;
463 }
464 
466 {
468 
469  ERR("Leftover sampler %p.\n", sampler);
470 }
471 
473 {
475 
476  TRACE("%p decreasing refcount to %u.\n", device, refcount);
477 
478  if (!refcount)
479  {
480  UINT i;
481 
483 
484  if (device->recording && wined3d_stateblock_decref(device->recording))
485  ERR("Something's still holding the recording stateblock.\n");
486  device->recording = NULL;
487 
488  state_cleanup(&device->state);
489 
490  for (i = 0; i < ARRAY_SIZE(device->multistate_funcs); ++i)
491  {
492  heap_free(device->multistate_funcs[i]);
493  device->multistate_funcs[i] = NULL;
494  }
495 
496  if (!list_empty(&device->resources))
497  {
498  struct wined3d_resource *resource;
499 
500  ERR("Device released with resources still bound.\n");
501 
503  {
504  ERR("Leftover resource %p with type %s (%#x).\n",
506  }
507  }
508 
509  if (device->contexts)
510  ERR("Context array not freed!\n");
511  if (device->hardwareCursor)
512  DestroyCursor(device->hardwareCursor);
513  device->hardwareCursor = 0;
514 
516 
517  wined3d_decref(device->wined3d);
518  device->wined3d = NULL;
519  heap_free(device);
520  TRACE("Freed device %p.\n", device);
521  }
522 
523  return refcount;
524 }
525 
527 {
528  TRACE("device %p.\n", device);
529 
530  return device->swapchain_count;
531 }
532 
534 {
535  TRACE("device %p, swapchain_idx %u.\n", device, swapchain_idx);
536 
537  if (swapchain_idx >= device->swapchain_count)
538  {
539  WARN("swapchain_idx %u >= swapchain_count %u.\n",
540  swapchain_idx, device->swapchain_count);
541  return NULL;
542  }
543 
544  return device->swapchains[swapchain_idx];
545 }
546 
547 static void device_load_logo(struct wined3d_device *device, const char *filename)
548 {
551  HBITMAP hbm;
552  BITMAP bm;
553  HRESULT hr;
554  HDC dcb = NULL, dcs = NULL;
555 
557  {
558  ERR_(winediag)("Failed to load logo %s.\n", wine_dbgstr_a(filename));
559  return;
560  }
561  GetObjectA(hbm, sizeof(BITMAP), &bm);
562 
563  if (!(dcb = CreateCompatibleDC(NULL)))
564  goto out;
565  SelectObject(dcb, hbm);
566 
567  desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
568  desc.format = WINED3DFMT_B5G6R5_UNORM;
569  desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
570  desc.multisample_quality = 0;
571  desc.usage = WINED3DUSAGE_DYNAMIC;
573  desc.width = bm.bmWidth;
574  desc.height = bm.bmHeight;
575  desc.depth = 1;
576  desc.size = 0;
579  NULL, NULL, &wined3d_null_parent_ops, &device->logo_texture)))
580  {
581  ERR("Wine logo requested, but failed to create texture, hr %#x.\n", hr);
582  goto out;
583  }
584 
585  if (FAILED(hr = wined3d_texture_get_dc(device->logo_texture, 0, &dcs)))
586  {
587  wined3d_texture_decref(device->logo_texture);
588  device->logo_texture = NULL;
589  goto out;
590  }
591  BitBlt(dcs, 0, 0, bm.bmWidth, bm.bmHeight, dcb, 0, 0, SRCCOPY);
592  wined3d_texture_release_dc(device->logo_texture, 0, dcs);
593 
594  color_key.color_space_low_value = 0;
595  color_key.color_space_high_value = 0;
597 
598 out:
599  if (dcb) DeleteDC(dcb);
600  if (hbm) DeleteObject(hbm);
601 }
602 
603 /* Context activation is done by the caller. */
605 {
606  const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
607  const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
608  struct wined3d_dummy_textures *textures = &device->dummy_textures;
609  unsigned int i;
610  DWORD color;
611 
613  color = 0x000000ff;
614  else
615  color = 0x00000000;
616 
617  /* Under DirectX you can sample even if no texture is bound, whereas
618  * OpenGL will only allow that when a valid texture is bound.
619  * We emulate this by creating dummy textures and binding them
620  * to each texture stage when the currently set D3D texture is NULL. */
621  context_active_texture(context, gl_info, 0);
622 
623  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_1d);
624  TRACE("Dummy 1D texture given name %u.\n", textures->tex_1d);
625  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, textures->tex_1d);
626  gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA8, 1, 0,
628 
629  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d);
630  TRACE("Dummy 2D texture given name %u.\n", textures->tex_2d);
631  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, textures->tex_2d);
632  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0,
634 
635  if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
636  {
637  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_rect);
638  TRACE("Dummy rectangle texture given name %u.\n", textures->tex_rect);
639  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textures->tex_rect);
640  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, 1, 1, 0,
642  }
643 
644  if (gl_info->supported[EXT_TEXTURE3D])
645  {
646  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_3d);
647  TRACE("Dummy 3D texture given name %u.\n", textures->tex_3d);
648  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_3D, textures->tex_3d);
651  }
652 
653  if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
654  {
655  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_cube);
656  TRACE("Dummy cube texture given name %u.\n", textures->tex_cube);
657  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP, textures->tex_cube);
659  {
660  gl_info->gl_ops.gl.p_glTexImage2D(i, 0, GL_RGBA8, 1, 1, 0,
662  }
663  }
664 
666  {
667  DWORD cube_array_data[6];
668 
669  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_cube_array);
670  TRACE("Dummy cube array texture given name %u.\n", textures->tex_cube_array);
671  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures->tex_cube_array);
672  for (i = 0; i < ARRAY_SIZE(cube_array_data); ++i)
673  cube_array_data[i] = color;
675  GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, cube_array_data));
676  }
677 
678  if (gl_info->supported[EXT_TEXTURE_ARRAY])
679  {
680 
681  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_1d_array);
682  TRACE("Dummy 1D array texture given name %u.\n", textures->tex_1d_array);
683  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D_ARRAY, textures->tex_1d_array);
684  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, GL_RGBA8, 1, 1, 0,
686 
687  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_array);
688  TRACE("Dummy 2D array texture given name %u.\n", textures->tex_2d_array);
689  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_ARRAY, textures->tex_2d_array);
692  }
693 
694  if (gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT])
695  {
696  GLuint buffer;
697 
698  GL_EXTCALL(glGenBuffers(1, &buffer));
699  GL_EXTCALL(glBindBuffer(GL_TEXTURE_BUFFER, buffer));
700  GL_EXTCALL(glBufferData(GL_TEXTURE_BUFFER, sizeof(color), &color, GL_STATIC_DRAW));
701  GL_EXTCALL(glBindBuffer(GL_TEXTURE_BUFFER, 0));
702 
703  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_buffer);
704  TRACE("Dummy buffer texture given name %u.\n", textures->tex_buffer);
705  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_BUFFER, textures->tex_buffer);
707  GL_EXTCALL(glDeleteBuffers(1, &buffer));
708  }
709 
710  if (gl_info->supported[ARB_TEXTURE_MULTISAMPLE])
711  {
712  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_ms);
713  TRACE("Dummy multisample texture given name %u.\n", textures->tex_2d_ms);
714  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures->tex_2d_ms);
715  GL_EXTCALL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_TRUE));
716 
717  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_ms_array);
718  TRACE("Dummy multisample array texture given name %u.\n", textures->tex_2d_ms_array);
719  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures->tex_2d_ms_array);
720  GL_EXTCALL(glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 1, GL_RGBA8, 1, 1, 1, GL_TRUE));
721 
722  if (gl_info->supported[ARB_CLEAR_TEXTURE])
723  {
724  GL_EXTCALL(glClearTexImage(textures->tex_2d_ms, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color));
725  GL_EXTCALL(glClearTexImage(textures->tex_2d_ms_array, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color));
726  }
727  else
728  {
729  WARN("ARB_clear_texture is currently required to clear dummy multisample textures.\n");
730  }
731  }
732 
733  checkGLcall("create dummy textures");
734 
736 }
737 
738 /* Context activation is done by the caller. */
740 {
741  struct wined3d_dummy_textures *dummy_textures = &device->dummy_textures;
742  const struct wined3d_gl_info *gl_info = context->gl_info;
743 
744  if (gl_info->supported[ARB_TEXTURE_MULTISAMPLE])
745  {
746  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_ms);
747  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_ms_array);
748  }
749 
750  if (gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT])
751  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_buffer);
752 
753  if (gl_info->supported[EXT_TEXTURE_ARRAY])
754  {
755  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_1d_array);
756  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_array);
757  }
758 
760  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_cube_array);
761 
762  if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
763  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_cube);
764 
765  if (gl_info->supported[EXT_TEXTURE3D])
766  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_3d);
767 
768  if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
769  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_rect);
770 
771  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d);
772  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_1d);
773 
774  checkGLcall("delete dummy textures");
775 
776  memset(dummy_textures, 0, sizeof(*dummy_textures));
777 }
778 
779 /* Context activation is done by the caller. */
781 {
782  struct wined3d_sampler_desc desc;
783  HRESULT hr;
784 
785  desc.address_u = WINED3D_TADDRESS_WRAP;
786  desc.address_v = WINED3D_TADDRESS_WRAP;
787  desc.address_w = WINED3D_TADDRESS_WRAP;
788  memset(desc.border_color, 0, sizeof(desc.border_color));
789  desc.mag_filter = WINED3D_TEXF_POINT;
790  desc.min_filter = WINED3D_TEXF_POINT;
791  desc.mip_filter = WINED3D_TEXF_NONE;
792  desc.lod_bias = 0.0f;
793  desc.min_lod = -1000.0f;
794  desc.max_lod = 1000.0f;
795  desc.mip_base_level = 0;
796  desc.max_anisotropy = 1;
797  desc.compare = FALSE;
798  desc.comparison_func = WINED3D_CMP_NEVER;
799  desc.srgb_decode = TRUE;
800 
801  /* In SM4+ shaders there is a separation between resources and samplers. Some shader
802  * instructions allow access to resources without using samplers.
803  * In GLSL, resources are always accessed through sampler or image variables. The default
804  * sampler object is used to emulate the direct resource access when there is no sampler state
805  * to use.
806  */
808  {
809  ERR("Failed to create default sampler, hr %#x.\n", hr);
810  device->default_sampler = NULL;
811  }
812 
813  /* In D3D10+, a NULL sampler maps to the default sampler state. */
814  desc.address_u = WINED3D_TADDRESS_CLAMP;
815  desc.address_v = WINED3D_TADDRESS_CLAMP;
816  desc.address_w = WINED3D_TADDRESS_CLAMP;
817  desc.mag_filter = WINED3D_TEXF_LINEAR;
818  desc.min_filter = WINED3D_TEXF_LINEAR;
819  desc.mip_filter = WINED3D_TEXF_LINEAR;
821  {
822  ERR("Failed to create null sampler, hr %#x.\n", hr);
823  device->null_sampler = NULL;
824  }
825 }
826 
827 /* Context activation is done by the caller. */
829 {
830  wined3d_sampler_decref(device->default_sampler);
831  device->default_sampler = NULL;
832  wined3d_sampler_decref(device->null_sampler);
833  device->null_sampler = NULL;
834 }
835 
837 {
838  /* Make sure the window is managed, otherwise we won't get keyboard input. */
841 
842  return style;
843 }
844 
845 static LONG fullscreen_exstyle(LONG exstyle)
846 {
847  /* Filter out window decorations. */
848  exstyle &= ~(WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE);
849 
850  return exstyle;
851 }
852 
854 {
855  BOOL filter_messages;
856  LONG style, exstyle;
857 
858  TRACE("Setting up window %p for fullscreen mode.\n", window);
859 
860  if (device->style || device->exStyle)
861  {
862  ERR("Changing the window style for window %p, but another style (%08x, %08x) is already stored.\n",
863  window, device->style, device->exStyle);
864  }
865 
868 
869  style = fullscreen_style(device->style);
870  exstyle = fullscreen_exstyle(device->exStyle);
871 
872  TRACE("Old style was %08x, %08x, setting to %08x, %08x.\n",
873  device->style, device->exStyle, style, exstyle);
874 
875  filter_messages = device->filter_messages;
876  device->filter_messages = TRUE;
877 
879  SetWindowLongW(window, GWL_EXSTYLE, exstyle);
881 
882  device->filter_messages = filter_messages;
883 }
884 
886  const RECT *window_rect)
887 {
888  unsigned int window_pos_flags = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE;
889  BOOL filter_messages;
890  LONG style, exstyle;
891  RECT rect = {0};
892 
893  if (!device->style && !device->exStyle)
894  return;
895 
897  exstyle = GetWindowLongW(window, GWL_EXSTYLE);
898 
899  /* These flags are set by wined3d_device_setup_fullscreen_window, not the
900  * application, and we want to ignore them in the test below, since it's
901  * not the application's fault that they changed. Additionally, we want to
902  * preserve the current status of these flags (i.e. don't restore them) to
903  * more closely emulate the behavior of Direct3D, which leaves these flags
904  * alone when returning to windowed mode. */
905  device->style ^= (device->style ^ style) & WS_VISIBLE;
906  device->exStyle ^= (device->exStyle ^ exstyle) & WS_EX_TOPMOST;
907 
908  TRACE("Restoring window style of window %p to %08x, %08x.\n",
909  window, device->style, device->exStyle);
910 
911  filter_messages = device->filter_messages;
912  device->filter_messages = TRUE;
913 
914  /* Only restore the style if the application didn't modify it during the
915  * fullscreen phase. Some applications change it before calling Reset()
916  * when switching between windowed and fullscreen modes (HL2), some
917  * depend on the original style (Eve Online). */
918  if (style == fullscreen_style(device->style) && exstyle == fullscreen_exstyle(device->exStyle))
919  {
922  }
923 
924  if (window_rect)
925  rect = *window_rect;
926  else
927  window_pos_flags |= (SWP_NOMOVE | SWP_NOSIZE);
928  SetWindowPos(window, 0, rect.left, rect.top,
929  rect.right - rect.left, rect.bottom - rect.top, window_pos_flags);
930 
931  device->filter_messages = filter_messages;
932 
933  /* Delete the old values. */
934  device->style = 0;
935  device->exStyle = 0;
936 }
937 
939 {
940  TRACE("device %p, window %p.\n", device, window);
941 
943  {
944  ERR("Failed to register window %p.\n", window);
945  return E_FAIL;
946  }
947 
948  InterlockedExchangePointer((void **)&device->focus_window, window);
949  SetWindowPos(window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
950 
951  return WINED3D_OK;
952 }
953 
955 {
956  TRACE("device %p.\n", device);
957 
958  if (device->focus_window) wined3d_unregister_window(device->focus_window);
959  InterlockedExchangePointer((void **)&device->focus_window, NULL);
960 }
961 
963 {
964  BOOL ds_enable = swapchain->desc.enable_auto_depth_stencil;
965  unsigned int i;
966 
967  for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
968  {
970  }
971  if (device->back_buffer_view)
972  wined3d_device_set_rendertarget_view(device, 0, device->back_buffer_view, TRUE);
973 
974  wined3d_device_set_depth_stencil_view(device, ds_enable ? device->auto_depth_stencil_view : NULL);
975 }
976 
978 {
979  struct wined3d_resource *resource, *cursor;
980  struct wined3d_device *device = object;
981  struct wined3d_context *context;
982  struct wined3d_shader *shader;
983 
984  LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry)
985  {
986  TRACE("Unloading resource %p.\n", resource);
988  }
989 
991  {
992  device->shader_backend->shader_destroy(shader);
993  }
994 
996  device->blitter->ops->blitter_destroy(device->blitter, context);
997  device->shader_backend->shader_free_private(device);
1001 
1002  while (device->context_count)
1003  {
1004  if (device->contexts[0]->swapchain)
1005  swapchain_destroy_contexts(device->contexts[0]->swapchain);
1006  else
1007  context_destroy(device, device->contexts[0]);
1008  }
1009 }
1010 
1012 {
1014  device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
1015 }
1016 
1018 {
1019  struct wined3d_device *device = object;
1020  struct wined3d_swapchain *swapchain;
1021  struct wined3d_context *context;
1022  struct wined3d_texture *target;
1023  HRESULT hr;
1024 
1025  if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
1026  device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
1027  {
1028  ERR("Failed to allocate shader private data, hr %#x.\n", hr);
1029  return;
1030  }
1031 
1032  if (!(device->blitter = wined3d_cpu_blitter_create()))
1033  {
1034  ERR("Failed to create CPU blitter.\n");
1035  device->shader_backend->shader_free_private(device);
1036  return;
1037  }
1038  wined3d_ffp_blitter_create(&device->blitter, &device->adapter->gl_info);
1040  wined3d_fbo_blitter_create(&device->blitter, &device->adapter->gl_info);
1041  wined3d_raw_blitter_create(&device->blitter, &device->adapter->gl_info);
1042 
1043  swapchain = device->swapchains[0];
1044  target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer;
1049 }
1050 
1052 {
1054  device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
1055  if (!device->swapchains[0]->num_contexts)
1056  return E_FAIL;
1057 
1058  return WINED3D_OK;
1059 }
1060 
1062  struct wined3d_swapchain_desc *swapchain_desc)
1063 {
1064  static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 0.0f};
1065  struct wined3d_swapchain *swapchain = NULL;
1066  DWORD clear_flags = 0;
1067  HRESULT hr;
1068 
1069  TRACE("device %p, swapchain_desc %p.\n", device, swapchain_desc);
1070 
1071  if (device->d3d_initialized)
1072  return WINED3DERR_INVALIDCALL;
1073  if (device->wined3d->flags & WINED3D_NO3D)
1074  return WINED3DERR_INVALIDCALL;
1075 
1076  memset(device->fb.render_targets, 0, sizeof(device->fb.render_targets));
1077 
1078  /* Setup the implicit swapchain. This also initializes a context. */
1079  TRACE("Creating implicit swapchain.\n");
1080  if (FAILED(hr = device->device_parent->ops->create_swapchain(device->device_parent,
1081  swapchain_desc, &swapchain)))
1082  {
1083  WARN("Failed to create implicit swapchain.\n");
1084  goto err_out;
1085  }
1086 
1087  if (swapchain_desc->backbuffer_count)
1088  {
1089  struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource;
1090  struct wined3d_view_desc view_desc;
1091 
1092  view_desc.format_id = back_buffer->format->id;
1093  view_desc.flags = 0;
1094  view_desc.u.texture.level_idx = 0;
1095  view_desc.u.texture.level_count = 1;
1096  view_desc.u.texture.layer_idx = 0;
1097  view_desc.u.texture.layer_count = 1;
1098  if (FAILED(hr = wined3d_rendertarget_view_create(&view_desc, back_buffer,
1099  NULL, &wined3d_null_parent_ops, &device->back_buffer_view)))
1100  {
1101  ERR("Failed to create rendertarget view, hr %#x.\n", hr);
1102  goto err_out;
1103  }
1104  }
1105 
1106  device->swapchain_count = 1;
1107  if (!(device->swapchains = heap_calloc(device->swapchain_count, sizeof(*device->swapchains))))
1108  {
1109  ERR("Out of memory!\n");
1110  goto err_out;
1111  }
1112  device->swapchains[0] = swapchain;
1113 
1115  goto err_out;
1116  device_init_swapchain_state(device, swapchain);
1117 
1118  device->contexts[0]->last_was_rhw = 0;
1119 
1120  TRACE("All defaults now set up.\n");
1121 
1122  /* Clear the screen */
1123  if (swapchain->back_buffers && swapchain->back_buffers[0])
1124  clear_flags |= WINED3DCLEAR_TARGET;
1125  if (swapchain_desc->enable_auto_depth_stencil)
1126  clear_flags |= WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL;
1127  if (clear_flags)
1128  wined3d_device_clear(device, 0, NULL, clear_flags, &black, 1.0f, 0);
1129 
1130  device->d3d_initialized = TRUE;
1131 
1132  if (wined3d_settings.logo)
1134  return WINED3D_OK;
1135 
1136 err_out:
1137  heap_free(device->swapchains);
1138  device->swapchain_count = 0;
1139  if (device->back_buffer_view)
1140  wined3d_rendertarget_view_decref(device->back_buffer_view);
1141  if (swapchain)
1142  wined3d_swapchain_decref(swapchain);
1143 
1144  return hr;
1145 }
1146 
1148  struct wined3d_swapchain_desc *swapchain_desc)
1149 {
1150  struct wined3d_swapchain *swapchain = NULL;
1151  HRESULT hr;
1152 
1153  TRACE("device %p, swapchain_desc %p.\n", device, swapchain_desc);
1154 
1155  /* Setup the implicit swapchain */
1156  TRACE("Creating implicit swapchain\n");
1157  hr = device->device_parent->ops->create_swapchain(device->device_parent,
1158  swapchain_desc, &swapchain);
1159  if (FAILED(hr))
1160  {
1161  WARN("Failed to create implicit swapchain\n");
1162  goto err_out;
1163  }
1164 
1165  device->swapchain_count = 1;
1166  if (!(device->swapchains = heap_calloc(device->swapchain_count, sizeof(*device->swapchains))))
1167  {
1168  ERR("Out of memory!\n");
1169  goto err_out;
1170  }
1171  device->swapchains[0] = swapchain;
1172 
1173  if (!(device->blitter = wined3d_cpu_blitter_create()))
1174  {
1175  ERR("Failed to create CPU blitter.\n");
1176  heap_free(device->swapchains);
1177  device->swapchain_count = 0;
1178  goto err_out;
1179  }
1180 
1181  return WINED3D_OK;
1182 
1183 err_out:
1184  wined3d_swapchain_decref(swapchain);
1185  return hr;
1186 }
1187 
1188 static void device_free_sampler(struct wine_rb_entry *entry, void *context)
1189 {
1191 
1193 }
1194 
1196 {
1197  unsigned int i;
1198 
1199  TRACE("device %p.\n", device);
1200 
1201  if (!device->d3d_initialized)
1202  return WINED3DERR_INVALIDCALL;
1203 
1204  device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
1205 
1206  if (device->logo_texture)
1207  wined3d_texture_decref(device->logo_texture);
1208  if (device->cursor_texture)
1209  wined3d_texture_decref(device->cursor_texture);
1210 
1211  state_unbind_resources(&device->state);
1212 
1214 
1215 #if defined(STAGING_CSMT)
1217 #endif /* STAGING_CSMT */
1219 
1220  if (device->fb.depth_stencil)
1221  {
1222  struct wined3d_rendertarget_view *view = device->fb.depth_stencil;
1223 
1224  TRACE("Releasing depth/stencil view %p.\n", view);
1225 
1226  device->fb.depth_stencil = NULL;
1228  }
1229 
1230  if (device->auto_depth_stencil_view)
1231  {
1232  struct wined3d_rendertarget_view *view = device->auto_depth_stencil_view;
1233 
1234  device->auto_depth_stencil_view = NULL;
1236  ERR("Something's still holding the auto depth/stencil view (%p).\n", view);
1237  }
1238 
1239  for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
1240  {
1242  }
1243  if (device->back_buffer_view)
1244  {
1245  wined3d_rendertarget_view_decref(device->back_buffer_view);
1246  device->back_buffer_view = NULL;
1247  }
1248 
1249  for (i = 0; i < device->swapchain_count; ++i)
1250  {
1251  TRACE("Releasing the implicit swapchain %u.\n", i);
1252  if (wined3d_swapchain_decref(device->swapchains[i]))
1253  FIXME("Something's still holding the implicit swapchain.\n");
1254  }
1255 
1256  heap_free(device->swapchains);
1257  device->swapchains = NULL;
1258  device->swapchain_count = 0;
1259 
1260  device->d3d_initialized = FALSE;
1261 
1262  return WINED3D_OK;
1263 }
1264 
1266 {
1267  unsigned int i;
1268 
1269  device->blitter->ops->blitter_destroy(device->blitter, NULL);
1270 
1271  for (i = 0; i < device->swapchain_count; ++i)
1272  {
1273  TRACE("Releasing the implicit swapchain %u.\n", i);
1274  if (wined3d_swapchain_decref(device->swapchains[i]))
1275  FIXME("Something's still holding the implicit swapchain.\n");
1276  }
1277 
1278  heap_free(device->swapchains);
1279  device->swapchains = NULL;
1280  device->swapchain_count = 0;
1281  return WINED3D_OK;
1282 }
1283 
1284 /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
1285  * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
1286  * CreateDevice if D3DCREATE_MULTITHREADED is passed.
1287  *
1288  * There is no way to deactivate thread safety once it is enabled.
1289  */
1291 {
1292  TRACE("device %p.\n", device);
1293 
1294  /* For now just store the flag (needed in case of ddraw). */
1295  device->create_parms.flags |= WINED3DCREATE_MULTITHREADED;
1296 }
1297 
1299 {
1300  /* const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; */
1301 
1302  TRACE("device %p.\n", device);
1303 
1304  /* We can not acquire the context unless there is a swapchain. */
1305  /*
1306  if (device->swapchains && gl_info->supported[NVX_GPU_MEMORY_INFO] &&
1307  !wined3d_settings.emulated_textureram)
1308  {
1309  GLint vram_free_kb;
1310  UINT64 vram_free;
1311 
1312  struct wined3d_context *context = context_acquire(device, NULL, 0);
1313  gl_info->gl_ops.gl.p_glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &vram_free_kb);
1314  vram_free = (UINT64)vram_free_kb * 1024;
1315  context_release(context);
1316 
1317  TRACE("Total 0x%s bytes. emulation 0x%s left, driver 0x%s left.\n",
1318  wine_dbgstr_longlong(device->adapter->vram_bytes),
1319  wine_dbgstr_longlong(device->adapter->vram_bytes - device->adapter->vram_bytes_used),
1320  wine_dbgstr_longlong(vram_free));
1321 
1322  vram_free = min(vram_free, device->adapter->vram_bytes - device->adapter->vram_bytes_used);
1323  return min(UINT_MAX, vram_free);
1324  }
1325  */
1326 
1327  TRACE("Emulating 0x%s bytes. 0x%s used, returning 0x%s left.\n",
1328  wine_dbgstr_longlong(device->adapter->vram_bytes),
1329  wine_dbgstr_longlong(device->adapter->vram_bytes_used),
1330  wine_dbgstr_longlong(device->adapter->vram_bytes - device->adapter->vram_bytes_used));
1331 
1332  return min(UINT_MAX, device->adapter->vram_bytes - device->adapter->vram_bytes_used);
1333 }
1334 
1336  struct wined3d_buffer *buffer, UINT offset)
1337 {
1338  struct wined3d_stream_output *stream;
1339  struct wined3d_buffer *prev_buffer;
1340 
1341  TRACE("device %p, idx %u, buffer %p, offset %u.\n", device, idx, buffer, offset);
1342 
1344  {
1345  WARN("Invalid stream output %u.\n", idx);
1346  return;
1347  }
1348 
1349  stream = &device->update_state->stream_output[idx];
1350  prev_buffer = stream->buffer;
1351 
1352  if (buffer)
1354  stream->buffer = buffer;
1355  stream->offset = offset;
1356  if (!device->recording)
1358  if (prev_buffer)
1359  wined3d_buffer_decref(prev_buffer);
1360 }
1361 
1363  UINT idx, UINT *offset)
1364 {
1365  TRACE("device %p, idx %u, offset %p.\n", device, idx, offset);
1366 
1368  {
1369  WARN("Invalid stream output %u.\n", idx);
1370  return NULL;
1371  }
1372 
1373  if (offset)
1374  *offset = device->state.stream_output[idx].offset;
1375  return device->state.stream_output[idx].buffer;
1376 }
1377 
1380 {
1381  struct wined3d_stream_state *stream;
1382  struct wined3d_buffer *prev_buffer;
1383 
1384  TRACE("device %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
1385  device, stream_idx, buffer, offset, stride);
1386 
1387  if (stream_idx >= MAX_STREAMS)
1388  {
1389  WARN("Stream index %u out of range.\n", stream_idx);
1390  return WINED3DERR_INVALIDCALL;
1391  }
1392  else if (offset & 0x3)
1393  {
1394  WARN("Offset %u is not 4 byte aligned.\n", offset);
1395  return WINED3DERR_INVALIDCALL;
1396  }
1397 
1398  stream = &device->update_state->streams[stream_idx];
1399  prev_buffer = stream->buffer;
1400 
1401  if (device->recording)
1402  device->recording->changed.streamSource |= 1u << stream_idx;
1403 
1404  if (prev_buffer == buffer
1405  && stream->stride == stride
1406  && stream->offset == offset)
1407  {
1408  TRACE("Application is setting the old values over, nothing to do.\n");
1409  return WINED3D_OK;
1410  }
1411 
1412  stream->buffer = buffer;
1413  if (buffer)
1414  {
1415  stream->stride = stride;
1416  stream->offset = offset;
1418  }
1419 
1420  if (!device->recording)
1422  if (prev_buffer)
1423  wined3d_buffer_decref(prev_buffer);
1424 
1425  return WINED3D_OK;
1426 }
1427 
1429  UINT stream_idx, struct wined3d_buffer **buffer, UINT *offset, UINT *stride)
1430 {
1431  const struct wined3d_stream_state *stream;
1432 
1433  TRACE("device %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
1434  device, stream_idx, buffer, offset, stride);
1435 
1436  if (stream_idx >= MAX_STREAMS)
1437  {
1438  WARN("Stream index %u out of range.\n", stream_idx);
1439  return WINED3DERR_INVALIDCALL;
1440  }
1441 
1442  stream = &device->state.streams[stream_idx];
1443  *buffer = stream->buffer;
1444  if (offset)
1445  *offset = stream->offset;
1446  *stride = stream->stride;
1447 
1448  return WINED3D_OK;
1449 }
1450 
1452 {
1453  struct wined3d_stream_state *stream;
1454  UINT old_flags, old_freq;
1455 
1456  TRACE("device %p, stream_idx %u, divider %#x.\n", device, stream_idx, divider);
1457 
1458  /* Verify input. At least in d3d9 this is invalid. */
1460  {
1461  WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL.\n");
1462  return WINED3DERR_INVALIDCALL;
1463  }
1464  if ((divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && !stream_idx)
1465  {
1466  WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL.\n");
1467  return WINED3DERR_INVALIDCALL;
1468  }
1469  if (!divider)
1470  {
1471  WARN("Divider is 0, returning D3DERR_INVALIDCALL.\n");
1472  return WINED3DERR_INVALIDCALL;
1473  }
1474 
1475  stream = &device->update_state->streams[stream_idx];
1476  old_flags = stream->flags;
1477  old_freq = stream->frequency;
1478 
1480  stream->frequency = divider & 0x7fffff;
1481 
1482  if (device->recording)
1483  device->recording->changed.streamFreq |= 1u << stream_idx;
1484  else if (stream->frequency != old_freq || stream->flags != old_flags)
1485  wined3d_cs_emit_set_stream_source_freq(device->cs, stream_idx, stream->frequency, stream->flags);
1486 
1487  return WINED3D_OK;
1488 }
1489 
1491  UINT stream_idx, UINT *divider)
1492 {
1493  const struct wined3d_stream_state *stream;
1494 
1495  TRACE("device %p, stream_idx %u, divider %p.\n", device, stream_idx, divider);
1496 
1497  stream = &device->state.streams[stream_idx];
1498  *divider = stream->flags | stream->frequency;
1499 
1500  TRACE("Returning %#x.\n", *divider);
1501 
1502  return WINED3D_OK;
1503 }
1504 
1506  enum wined3d_transform_state d3dts, const struct wined3d_matrix *matrix)
1507 {
1508  TRACE("device %p, state %s, matrix %p.\n",
1509  device, debug_d3dtstype(d3dts), matrix);
1510  TRACE("%.8e %.8e %.8e %.8e\n", matrix->_11, matrix->_12, matrix->_13, matrix->_14);
1511  TRACE("%.8e %.8e %.8e %.8e\n", matrix->_21, matrix->_22, matrix->_23, matrix->_24);
1512  TRACE("%.8e %.8e %.8e %.8e\n", matrix->_31, matrix->_32, matrix->_33, matrix->_34);
1513  TRACE("%.8e %.8e %.8e %.8e\n", matrix->_41, matrix->_42, matrix->_43, matrix->_44);
1514 
1515  /* Handle recording of state blocks. */
1516  if (device->recording)
1517  {
1518  TRACE("Recording... not performing anything.\n");
1519  device->recording->changed.transform[d3dts >> 5] |= 1u << (d3dts & 0x1f);
1520  device->update_state->transforms[d3dts] = *matrix;
1521  return;
1522  }
1523 
1524  /* If the new matrix is the same as the current one,
1525  * we cut off any further processing. this seems to be a reasonable
1526  * optimization because as was noticed, some apps (warcraft3 for example)
1527  * tend towards setting the same matrix repeatedly for some reason.
1528  *
1529  * From here on we assume that the new matrix is different, wherever it matters. */
1530  if (!memcmp(&device->state.transforms[d3dts], matrix, sizeof(*matrix)))
1531  {
1532  TRACE("The application is setting the same matrix over again.\n");
1533  return;
1534  }
1535 
1536  device->state.transforms[d3dts] = *matrix;
1538 }
1539 
1542 {
1543  TRACE("device %p, state %s, matrix %p.\n", device, debug_d3dtstype(state), matrix);
1544 
1545  *matrix = device->state.transforms[state];
1546 }
1547 
1549  enum wined3d_transform_state state, const struct wined3d_matrix *matrix)
1550 {
1551  const struct wined3d_matrix *mat;
1552  struct wined3d_matrix temp;
1553 
1554  TRACE("device %p, state %s, matrix %p.\n", device, debug_d3dtstype(state), matrix);
1555 
1556  /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1557  * below means it will be recorded in a state block change, but it
1558  * works regardless where it is recorded.
1559  * If this is found to be wrong, change to StateBlock. */
1561  {
1562  WARN("Unhandled transform state %#x.\n", state);
1563  return;
1564  }
1565 
1566  mat = &device->update_state->transforms[state];
1568 
1569  /* Apply change via set transform - will reapply to eg. lights this way. */
1571 }
1572 
1573 /* Note lights are real special cases. Although the device caps state only
1574  * e.g. 8 are supported, you can reference any indexes you want as long as
1575  * that number max are enabled at any one point in time. Therefore since the
1576  * indices can be anything, we need a hashmap of them. However, this causes
1577  * stateblock problems. When capturing the state block, I duplicate the
1578  * hashmap, but when recording, just build a chain pretty much of commands to
1579  * be replayed. */
1581  UINT light_idx, const struct wined3d_light *light)
1582 {
1583  UINT hash_idx = LIGHTMAP_HASHFUNC(light_idx);
1584  struct wined3d_light_info *object = NULL;
1585  float rho;
1586 
1587  TRACE("device %p, light_idx %u, light %p.\n", device, light_idx, light);
1588 
1589  /* Check the parameter range. Need for speed most wanted sets junk lights
1590  * which confuse the GL driver. */
1591  if (!light)
1592  return WINED3DERR_INVALIDCALL;
1593 
1594  switch (light->type)
1595  {
1596  case WINED3D_LIGHT_POINT:
1597  case WINED3D_LIGHT_SPOT:
1598  case WINED3D_LIGHT_GLSPOT:
1599  /* Incorrect attenuation values can cause the gl driver to crash.
1600  * Happens with Need for speed most wanted. */
1601  if (light->attenuation0 < 0.0f || light->attenuation1 < 0.0f || light->attenuation2 < 0.0f)
1602  {
1603  WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL.\n");
1604  return WINED3DERR_INVALIDCALL;
1605  }
1606  break;
1607 
1610  /* Ignores attenuation */
1611  break;
1612 
1613  default:
1614  WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
1615  return WINED3DERR_INVALIDCALL;
1616  }
1617 
1618  if (!(object = wined3d_state_get_light(device->update_state, light_idx)))
1619  {
1620  TRACE("Adding new light\n");
1621  if (!(object = heap_alloc_zero(sizeof(*object))))
1622  return E_OUTOFMEMORY;
1623 
1624  list_add_head(&device->update_state->light_map[hash_idx], &object->entry);
1625  object->glIndex = -1;
1626  object->OriginalIndex = light_idx;
1627  }
1628 
1629  /* Initialize the object. */
1630  TRACE("Light %u setting to type %#x, diffuse %s, specular %s, ambient %s, "
1631  "position {%.8e, %.8e, %.8e}, direction {%.8e, %.8e, %.8e}, "
1632  "range %.8e, falloff %.8e, theta %.8e, phi %.8e.\n",
1633  light_idx, light->type, debug_color(&light->diffuse),
1634  debug_color(&light->specular), debug_color(&light->ambient),
1635  light->position.x, light->position.y, light->position.z,
1636  light->direction.x, light->direction.y, light->direction.z,
1637  light->range, light->falloff, light->theta, light->phi);
1638 
1639  /* Save away the information. */
1640  object->OriginalParms = *light;
1641 
1642  switch (light->type)
1643  {
1644  case WINED3D_LIGHT_POINT:
1645  /* Position */
1646  object->position.x = light->position.x;
1647  object->position.y = light->position.y;
1648  object->position.z = light->position.z;
1649  object->position.w = 1.0f;
1650  object->cutoff = 180.0f;
1651  /* FIXME: Range */
1652  break;
1653 
1655  /* Direction */
1656  object->direction.x = -light->direction.x;
1657  object->direction.y = -light->direction.y;
1658  object->direction.z = -light->direction.z;
1659  object->direction.w = 0.0f;
1660  object->exponent = 0.0f;
1661  object->cutoff = 180.0f;
1662  break;
1663 
1664  case WINED3D_LIGHT_SPOT:
1665  /* Position */
1666  object->position.x = light->position.x;
1667  object->position.y = light->position.y;
1668  object->position.z = light->position.z;
1669  object->position.w = 1.0f;
1670 
1671  /* Direction */
1672  object->direction.x = light->direction.x;
1673  object->direction.y = light->direction.y;
1674  object->direction.z = light->direction.z;
1675  object->direction.w = 0.0f;
1676 
1677  /* opengl-ish and d3d-ish spot lights use too different models
1678  * for the light "intensity" as a function of the angle towards
1679  * the main light direction, so we only can approximate very
1680  * roughly. However, spot lights are rather rarely used in games
1681  * (if ever used at all). Furthermore if still used, probably
1682  * nobody pays attention to such details. */
1683  if (!light->falloff)
1684  {
1685  /* Falloff = 0 is easy, because d3d's and opengl's spot light
1686  * equations have the falloff resp. exponent parameter as an
1687  * exponent, so the spot light lighting will always be 1.0 for
1688  * both of them, and we don't have to care for the rest of the
1689  * rather complex calculation. */
1690  object->exponent = 0.0f;
1691  }
1692  else
1693  {
1694  rho = light->theta + (light->phi - light->theta) / (2 * light->falloff);
1695  if (rho < 0.0001f)
1696  rho = 0.0001f;
1697  object->exponent = -0.3f / logf(cosf(rho / 2));
1698  }
1699 
1700  if (object->exponent > 128.0f)
1701  object->exponent = 128.0f;
1702 
1703  object->cutoff = (float)(light->phi * 90 / M_PI);
1704  /* FIXME: Range */
1705  break;
1706 
1708  object->position.x = light->position.x;
1709  object->position.y = light->position.y;
1710  object->position.z = light->position.z;
1711  object->position.w = 1.0f;
1712  break;
1713 
1714  default:
1715  FIXME("Unrecognized light type %#x.\n", light->type);
1716  }
1717 
1718  if (!device->recording)
1719  wined3d_cs_emit_set_light(device->cs, object);
1720 
1721  return WINED3D_OK;
1722 }
1723 
1725  UINT light_idx, struct wined3d_light *light)
1726 {
1727  struct wined3d_light_info *light_info;
1728 
1729  TRACE("device %p, light_idx %u, light %p.\n", device, light_idx, light);
1730 
1731  if (!(light_info = wined3d_state_get_light(&device->state, light_idx)))
1732  {
1733  TRACE("Light information requested but light not defined\n");
1734  return WINED3DERR_INVALIDCALL;
1735  }
1736 
1737  *light = light_info->OriginalParms;
1738  return WINED3D_OK;
1739 }
1740 
1742 {
1743  struct wined3d_light_info *light_info;
1744 
1745  TRACE("device %p, light_idx %u, enable %#x.\n", device, light_idx, enable);
1746 
1747  /* Special case - enabling an undefined light creates one with a strict set of parameters. */
1748  if (!(light_info = wined3d_state_get_light(device->update_state, light_idx)))
1749  {
1750  TRACE("Light enabled requested but light not defined, so defining one!\n");
1752 
1753  if (!(light_info = wined3d_state_get_light(device->update_state, light_idx)))
1754  {
1755  FIXME("Adding default lights has failed dismally\n");
1756  return WINED3DERR_INVALIDCALL;
1757  }
1758  }
1759 
1760  wined3d_state_enable_light(device->update_state, &device->adapter->d3d_info, light_info, enable);
1761  if (!device->recording)
1763 
1764  return WINED3D_OK;
1765 }
1766 
1768 {
1769  struct wined3d_light_info *light_info;
1770 
1771  TRACE("device %p, light_idx %u, enable %p.\n", device, light_idx, enable);
1772 
1773  if (!(light_info = wined3d_state_get_light(&device->state, light_idx)))
1774  {
1775  TRACE("Light enabled state requested but light not defined.\n");
1776  return WINED3DERR_INVALIDCALL;
1777  }
1778  /* true is 128 according to SetLightEnable */
1779  *enable = light_info->enabled ? 128 : 0;
1780  return WINED3D_OK;
1781 }
1782 
1784  UINT plane_idx, const struct wined3d_vec4 *plane)
1785 {
1786  TRACE("device %p, plane_idx %u, plane %p.\n", device, plane_idx, plane);
1787 
1788  if (plane_idx >= device->adapter->gl_info.limits.user_clip_distances)
1789  {
1790  TRACE("Application has requested clipplane this device doesn't support.\n");
1791  return WINED3DERR_INVALIDCALL;
1792  }
1793 
1794  if (device->recording)
1795  device->recording->changed.clipplane |= 1u << plane_idx;
1796 
1797  if (!memcmp(&device->update_state->clip_planes[plane_idx], plane, sizeof(*plane)))
1798  {
1799  TRACE("Application is setting old values over, nothing to do.\n");
1800  return WINED3D_OK;
1801  }
1802 
1803  device->update_state->clip_planes[plane_idx] = *plane;
1804 
1805  if (!device->recording)
1806  wined3d_cs_emit_set_clip_plane(device->cs, plane_idx, plane);
1807 
1808  return WINED3D_OK;
1809 }
1810 
1812  UINT plane_idx, struct wined3d_vec4 *plane)
1813 {
1814  TRACE("device %p, plane_idx %u, plane %p.\n", device, plane_idx, plane);
1815 
1816  if (plane_idx >= device->adapter->gl_info.limits.user_clip_distances)
1817  {
1818  TRACE("Application has requested clipplane this device doesn't support.\n");
1819  return WINED3DERR_INVALIDCALL;
1820  }
1821 
1822  *plane = device->state.clip_planes[plane_idx];
1823 
1824  return WINED3D_OK;
1825 }
1826 
1828  const struct wined3d_clip_status *clip_status)
1829 {
1830  FIXME("device %p, clip_status %p stub!\n", device, clip_status);
1831 
1832  if (!clip_status)
1833  return WINED3DERR_INVALIDCALL;
1834 
1835  return WINED3D_OK;
1836 }
1837 
1839  struct wined3d_clip_status *clip_status)
1840 {
1841  FIXME("device %p, clip_status %p stub!\n", device, clip_status);
1842 
1843  if (!clip_status)
1844  return WINED3DERR_INVALIDCALL;
1845 
1846  return WINED3D_OK;
1847 }
1848 
1850 {
1851  TRACE("device %p, material %p.\n", device, material);
1852 
1853  device->update_state->material = *material;
1854 
1855  if (device->recording)
1856  device->recording->changed.material = TRUE;
1857  else
1858  wined3d_cs_emit_set_material(device->cs, material);
1859 }
1860 
1862 {
1863  TRACE("device %p, material %p.\n", device, material);
1864 
1865  *material = device->state.material;
1866 
1867  TRACE("diffuse %s\n", debug_color(&material->diffuse));
1868  TRACE("ambient %s\n", debug_color(&material->ambient));
1869  TRACE("specular %s\n", debug_color(&material->specular));
1870  TRACE("emissive %s\n", debug_color(&material->emissive));
1871  TRACE("power %.8e.\n", material->power);
1872 }
1873 
1875  struct wined3d_buffer *buffer, enum wined3d_format_id format_id, unsigned int offset)
1876 {
1877  enum wined3d_format_id prev_format;
1878  struct wined3d_buffer *prev_buffer;
1879  unsigned int prev_offset;
1880 
1881  TRACE("device %p, buffer %p, format %s, offset %u.\n",
1883 
1884  prev_buffer = device->update_state->index_buffer;
1885  prev_format = device->update_state->index_format;
1886  prev_offset = device->update_state->index_offset;
1887 
1888  device->update_state->index_buffer = buffer;
1889  device->update_state->index_format = format_id;
1890  device->update_state->index_offset = offset;
1891 
1892  if (device->recording)
1893  device->recording->changed.indices = TRUE;
1894 
1895  if (prev_buffer == buffer && prev_format == format_id && prev_offset == offset)
1896  return;
1897 
1898  if (buffer)
1900  if (!device->recording)
1902  if (prev_buffer)
1903  wined3d_buffer_decref(prev_buffer);
1904 }
1905 
1907  enum wined3d_format_id *format, unsigned int *offset)
1908 {
1909  TRACE("device %p, format %p, offset %p.\n", device, format, offset);
1910 
1911  *format = device->state.index_format;
1912  if (offset)
1913  *offset = device->state.index_offset;
1914  return device->state.index_buffer;
1915 }
1916 
1918 {
1919  TRACE("device %p, base_index %d.\n", device, base_index);
1920 
1921  device->update_state->base_vertex_index = base_index;
1922 }
1923 
1925 {
1926  TRACE("device %p.\n", device);
1927 
1928  return device->state.base_vertex_index;
1929 }
1930 
1932 {
1933  TRACE("device %p, viewport %p.\n", device, viewport);
1934  TRACE("x %.8e, y %.8e, w %.8e, h %.8e, min_z %.8e, max_z %.8e.\n",
1935  viewport->x, viewport->y, viewport->width, viewport->height, viewport->min_z, viewport->max_z);
1936 
1937  device->update_state->viewport = *viewport;
1938 
1939  /* Handle recording of state blocks */
1940  if (device->recording)
1941  {
1942  TRACE("Recording... not performing anything\n");
1943  device->recording->changed.viewport = TRUE;
1944  return;
1945  }
1946 
1947  wined3d_cs_emit_set_viewport(device->cs, viewport);
1948 }
1949 
1951 {
1952  TRACE("device %p, viewport %p.\n", device, viewport);
1953 
1954  *viewport = device->state.viewport;
1955 }
1956 
1958 {
1959  const struct wined3d_state *state = &device->state;
1960  struct wined3d_rendertarget_view *src_view;
1961  struct wined3d_resource *dst_resource;
1962  struct wined3d_texture *dst_texture;
1963 
1964  if (!(dst_texture = state->textures[0]))
1965  return;
1966  dst_resource = &dst_texture->resource;
1967  if (!(dst_resource->format_flags & WINED3DFMT_FLAG_DEPTH))
1968  return;
1969  if (!(src_view = state->fb->depth_stencil))
1970  return;
1971 
1973  src_view->resource, src_view->sub_resource_idx, dst_resource->format->id);
1974 }
1975 
1977 {
1978  struct wined3d_blend_state *prev;
1979 
1980  TRACE("device %p, blend_state %p.\n", device, blend_state);
1981 
1982  prev = device->update_state->blend_state;
1983  if (prev == blend_state)
1984  return;
1985 
1986  if (blend_state)
1987  wined3d_blend_state_incref(blend_state);
1988  device->update_state->blend_state = blend_state;
1989  wined3d_cs_emit_set_blend_state(device->cs, blend_state);
1990  if (prev)
1992 }
1993 
1995 {
1996  TRACE("device %p.\n", device);
1997 
1998  return device->state.blend_state;
1999 }
2000 
2002  struct wined3d_rasterizer_state *rasterizer_state)
2003 {
2004  struct wined3d_rasterizer_state *prev;
2005 
2006  TRACE("device %p, rasterizer_state %p.\n", device, rasterizer_state);
2007 
2008  prev = device->update_state->rasterizer_state;
2009  if (prev == rasterizer_state)
2010  return;
2011 
2012  if (rasterizer_state)
2013  wined3d_rasterizer_state_incref(rasterizer_state);
2014  device->update_state->rasterizer_state = rasterizer_state;
2015  wined3d_cs_emit_set_rasterizer_state(device->cs, rasterizer_state);
2016  if (prev)
2018 }
2019 
2021 {
2022  TRACE("device %p.\n", device);
2023 
2024  return device->state.rasterizer_state;
2025 }
2026 
2029 {
2030  DWORD old_value;
2031 
2032  TRACE("device %p, state %s (%#x), value %#x.\n", device, debug_d3drenderstate(state), state, value);
2033 
2035  {
2036  WARN("Unhandled render state %#x.\n", state);
2037  return;
2038  }
2039 
2040  old_value = device->state.render_states[state];
2041  device->update_state->render_states[state] = value;
2042 
2043  /* Handle recording of state blocks. */
2044  if (device->recording)
2045  {
2046  TRACE("Recording... not performing anything.\n");
2047  device->recording->changed.renderState[state >> 5] |= 1u << (state & 0x1f);
2048  return;
2049  }
2050 
2051  /* Compared here and not before the assignment to allow proper stateblock recording. */
2052  if (value == old_value)
2053  TRACE("Application is setting the old value over, nothing to do.\n");
2054  else
2056 
2058  {
2059  TRACE("RESZ multisampled depth buffer resolve triggered.\n");
2061  }
2062 }
2063 
2065 {
2066  TRACE("device %p, state %s (%#x).\n", device, debug_d3drenderstate(state), state);
2067 
2068  return device->state.render_states[state];
2069 }
2070 
2072  UINT sampler_idx, enum wined3d_sampler_state state, DWORD value)
2073 {
2074  DWORD old_value;
2075 
2076  TRACE("device %p, sampler_idx %u, state %s, value %#x.\n",
2077  device, sampler_idx, debug_d3dsamplerstate(state), value);
2078 
2079  if (sampler_idx >= WINED3DVERTEXTEXTURESAMPLER0 && sampler_idx <= WINED3DVERTEXTEXTURESAMPLER3)
2081 
2082  if (sampler_idx >= ARRAY_SIZE(device->state.sampler_states))
2083  {
2084  WARN("Invalid sampler %u.\n", sampler_idx);
2085  return; /* Windows accepts overflowing this array ... we do not. */
2086  }
2087 
2088  old_value = device->state.sampler_states[sampler_idx][state];
2089  device->update_state->sampler_states[sampler_idx][state] = value;
2090 
2091  /* Handle recording of state blocks. */
2092  if (device->recording)
2093  {
2094  TRACE("Recording... not performing anything.\n");
2095  device->recording->changed.samplerState[sampler_idx] |= 1u << state;
2096  return;
2097  }
2098 
2099  if (old_value == value)
2100  {
2101  TRACE("Application is setting the old value over, nothing to do.\n");
2102  return;
2103  }
2104 
2106 }
2107 
2109  UINT sampler_idx, enum wined3d_sampler_state state)
2110 {
2111  TRACE("device %p, sampler_idx %u, state %s.\n",
2112  device, sampler_idx, debug_d3dsamplerstate(state));
2113 
2114  if (sampler_idx >= WINED3DVERTEXTEXTURESAMPLER0 && sampler_idx <= WINED3DVERTEXTEXTURESAMPLER3)
2116 
2117  if (sampler_idx >= ARRAY_SIZE(device->state.sampler_states))
2118  {
2119  WARN("Invalid sampler %u.\n", sampler_idx);
2120  return 0; /* Windows accepts overflowing this array ... we do not. */
2121  }
2122 
2123  return device->state.sampler_states[sampler_idx][state];
2124 }
2125 
2127 {
2128  TRACE("device %p, rect %s.\n", device, wine_dbgstr_rect(rect));
2129 
2130  if (device->recording)
2131  device->recording->changed.scissorRect = TRUE;
2132 
2133  if (EqualRect(&device->update_state->scissor_rect, rect))
2134  {
2135  TRACE("App is setting the old scissor rectangle over, nothing to do.\n");
2136  return;
2137  }
2138  CopyRect(&device->update_state->scissor_rect, rect);
2139 
2140  if (device->recording)
2141  {
2142  TRACE("Recording... not performing anything.\n");
2143  return;
2144  }
2145 
2147 }
2148 
2150 {
2151  TRACE("device %p, rect %p.\n", device, rect);
2152 
2153  *rect = device->state.scissor_rect;
2154  TRACE("Returning rect %s.\n", wine_dbgstr_rect(rect));
2155 }
2156 
2159 {
2160  struct wined3d_vertex_declaration *prev = device->update_state->vertex_declaration;
2161 
2162  TRACE("device %p, declaration %p.\n", device, declaration);
2163 
2164  if (device->recording)
2165  device->recording->changed.vertexDecl = TRUE;
2166 
2167  if (declaration == prev)
2168  return;
2169 
2170  if (declaration)
2172  device->update_state->vertex_declaration = declaration;
2173  if (!device->recording)
2175  if (prev)
2177 }
2178 
2180 {
2181  TRACE("device %p.\n", device);
2182 
2183  return device->state.vertex_declaration;
2184 }
2185 
2187 {
2188  struct wined3d_shader *prev = device->update_state->shader[WINED3D_SHADER_TYPE_VERTEX];
2189 
2190  TRACE("device %p, shader %p.\n", device, shader);
2191 
2192  if (device->recording)
2193  device->recording->changed.vertexShader = TRUE;
2194 
2195  if (shader == prev)
2196  return;
2197 
2198  if (shader)
2200  device->update_state->shader[WINED3D_SHADER_TYPE_VERTEX] = shader;
2201  if (!device->recording)
2203  if (prev)
2204  wined3d_shader_decref(prev);
2205 }
2206 
2208 {
2209  TRACE("device %p.\n", device);
2210 
2211  return device->state.shader[WINED3D_SHADER_TYPE_VERTEX];
2212 }
2213 
2216 {
2217  struct wined3d_buffer *prev;
2218 
2219  if (idx >= MAX_CONSTANT_BUFFERS)
2220  {
2221  WARN("Invalid constant buffer index %u.\n", idx);
2222  return;
2223  }
2224 
2225  prev = device->update_state->cb[type][idx];
2226  if (buffer == prev)
2227  return;
2228 
2229  if (buffer)
2231  device->update_state->cb[type][idx] = buffer;
2232  if (!device->recording)
2234  if (prev)
2235  wined3d_buffer_decref(prev);
2236 }
2237 
2239 {
2240  TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2241 
2243 }
2244 
2246  enum wined3d_shader_type shader_type, unsigned int idx)
2247 {
2248  if (idx >= MAX_CONSTANT_BUFFERS)
2249  {
2250  WARN("Invalid constant buffer index %u.\n", idx);
2251  return NULL;
2252  }
2253 
2254  return device->state.cb[shader_type][idx];
2255 }
2256 
2258 {
2259  TRACE("device %p, idx %u.\n", device, idx);
2260 
2262 }
2263 
2266 {
2267  struct wined3d_shader_resource_view *prev;
2268 
2270  {
2271  WARN("Invalid view index %u.\n", idx);
2272  return;
2273  }
2274 
2275  prev = device->update_state->shader_resource_view[type][idx];
2276  if (view == prev)
2277  return;
2278 
2279  if (view)
2281  device->update_state->shader_resource_view[type][idx] = view;
2282  if (!device->recording)
2284  if (prev)
2286 }
2287 
2290 {
2291  TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2292 
2294 }
2295 
2297  const struct wined3d_device *device, enum wined3d_shader_type shader_type, unsigned int idx)
2298 {
2300  {
2301  WARN("Invalid view index %u.\n", idx);
2302  return NULL;
2303  }
2304 
2305  return device->state.shader_resource_view[shader_type][idx];
2306 }
2307 
2309  UINT idx)
2310 {
2311  TRACE("device %p, idx %u.\n", device, idx);
2312 
2314 }
2315 
2318 {
2319  struct wined3d_sampler *prev;
2320 
2321  if (idx >= MAX_SAMPLER_OBJECTS)
2322  {
2323  WARN("Invalid sampler index %u.\n", idx);
2324  return;
2325  }
2326 
2327  prev = device->update_state->sampler[type][idx];
2328  if (sampler == prev)
2329  return;
2330 
2331  if (sampler)
2333  device->update_state->sampler[type][idx] = sampler;
2334  if (!device->recording)
2336  if (prev)
2337  wined3d_sampler_decref(prev);
2338 }
2339 
2341 {
2342  TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2343 
2345 }
2346 
2348  enum wined3d_shader_type shader_type, unsigned int idx)
2349 {
2350  if (idx >= MAX_SAMPLER_OBJECTS)
2351  {
2352  WARN("Invalid sampler index %u.\n", idx);
2353  return NULL;
2354  }
2355 
2356  return device->state.sampler[shader_type][idx];
2357 }
2358 
2360 {
2361  TRACE("device %p, idx %u.\n", device, idx);
2362 
2364 }
2365 
2367  unsigned int start_idx, unsigned int count, const BOOL *constants)
2368 {
2369  unsigned int i;
2370 
2371  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2372  device, start_idx, count, constants);
2373 
2374  if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
2375  return WINED3DERR_INVALIDCALL;
2376 
2377  if (count > WINED3D_MAX_CONSTS_B - start_idx)
2378  count = WINED3D_MAX_CONSTS_B - start_idx;
2379  memcpy(&device->update_state->vs_consts_b[start_idx], constants, count * sizeof(*constants));
2380  if (TRACE_ON(d3d))
2381  {
2382  for (i = 0; i < count; ++i)
2383  TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]);
2384  }
2385 
2386  if (device->recording)
2387  {
2388  for (i = start_idx; i < count + start_idx; ++i)
2389  device->recording->changed.vertexShaderConstantsB |= (1u << i);
2390  }
2391  else
2392  {
2394  }
2395 
2396  return WINED3D_OK;
2397 }
2398 
2400  unsigned int start_idx, unsigned int count, BOOL *constants)
2401 {
2402  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2403  device, start_idx, count, constants);
2404 
2405  if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
2406  return WINED3DERR_INVALIDCALL;
2407 
2408  if (count > WINED3D_MAX_CONSTS_B - start_idx)
2409  count = WINED3D_MAX_CONSTS_B - start_idx;
2410  memcpy(constants, &device->state.vs_consts_b[start_idx], count * sizeof(*constants));
2411 
2412  return WINED3D_OK;
2413 }
2414 
2416  unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants)
2417 {
2418  unsigned int i;
2419 
2420  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2421  device, start_idx, count, constants);
2422 
2423  if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
2424  return WINED3DERR_INVALIDCALL;
2425 
2426  if (count > WINED3D_MAX_CONSTS_I - start_idx)
2427  count = WINED3D_MAX_CONSTS_I - start_idx;
2428  memcpy(&device->update_state->vs_consts_i[start_idx], constants, count * sizeof(*constants));
2429  if (TRACE_ON(d3d))
2430  {
2431  for (i = 0; i < count; ++i)
2432  TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i]));
2433  }
2434 
2435  if (device->recording)
2436  {
2437  for (i = start_idx; i < count + start_idx; ++i)
2438  device->recording->changed.vertexShaderConstantsI |= (1u << i);
2439  }
2440  else
2441  {
2443  }
2444 
2445  return WINED3D_OK;
2446 }
2447 
2449  unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants)
2450 {
2451  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2452  device, start_idx, count, constants);
2453 
2454  if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
2455  return WINED3DERR_INVALIDCALL;
2456 
2457  if (count > WINED3D_MAX_CONSTS_I - start_idx)
2458  count = WINED3D_MAX_CONSTS_I - start_idx;
2459  memcpy(constants, &device->state.vs_consts_i[start_idx], count * sizeof(*constants));
2460  return WINED3D_OK;
2461 }
2462 
2464  unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants)
2465 {
2466  const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
2467  unsigned int i;
2468 
2469  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2470  device, start_idx, count, constants);
2471 
2472  if (!constants || start_idx >= d3d_info->limits.vs_uniform_count
2473  || count > d3d_info->limits.vs_uniform_count - start_idx)
2474  return WINED3DERR_INVALIDCALL;
2475 
2476  memcpy(&device->update_state->vs_consts_f[start_idx], constants, count * sizeof(*constants));
2477  if (TRACE_ON(d3d))
2478  {
2479  for (i = 0; i < count; ++i)
2480  TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i]));
2481  }
2482 
2483  if (device->recording)
2484  memset(&device->recording->changed.vs_consts_f[start_idx], 1,
2485  count * sizeof(*device->recording->changed.vs_consts_f));
2486  else
2488 
2489  return WINED3D_OK;
2490 }
2491 
2493  unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants)
2494 {
2495  const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
2496 
2497  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2498  device, start_idx, count, constants);
2499 
2500  if (!constants || start_idx >= d3d_info->limits.vs_uniform_count
2501  || count > d3d_info->limits.vs_uniform_count - start_idx)
2502  return WINED3DERR_INVALIDCALL;
2503 
2504  memcpy(constants, &device->state.vs_consts_f[start_idx], count * sizeof(*constants));
2505 
2506  return WINED3D_OK;
2507 }
2508 
2510 {
2511  struct wined3d_shader *prev = device->update_state->shader[WINED3D_SHADER_TYPE_PIXEL];
2512 
2513  TRACE("device %p, shader %p.\n", device, shader);
2514 
2515  if (device->recording)
2516  device->recording->changed.pixelShader = TRUE;
2517 
2518  if (shader == prev)
2519  return;
2520 
2521  if (shader)
2523  device->update_state->shader[WINED3D_SHADER_TYPE_PIXEL] = shader;
2524  if (!device->recording)
2526  if (prev)
2527  wined3d_shader_decref(prev);
2528 }
2529 
2531 {
2532  TRACE("device %p.\n", device);
2533 
2534  return device->state.shader[WINED3D_SHADER_TYPE_PIXEL];
2535 }
2536 
2538 {
2539  TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2540 
2542 }
2543 
2545 {
2546  TRACE("device %p, idx %u.\n", device, idx);
2547 
2549 }
2550 
2553 {
2554  TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2555 
2557 }
2558 
2560  UINT idx)
2561 {
2562  TRACE("device %p, idx %u.\n", device, idx);
2563 
2565 }
2566 
2568 {
2569  TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2570 
2572 }
2573 
2575 {
2576  TRACE("device %p, idx %u.\n", device, idx);
2577 
2579 }
2580 
2582  unsigned int start_idx, unsigned int count, const BOOL *constants)
2583 {
2584  unsigned int i;
2585 
2586  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2587  device, start_idx, count, constants);
2588 
2589  if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
2590  return WINED3DERR_INVALIDCALL;
2591 
2592  if (count > WINED3D_MAX_CONSTS_B - start_idx)
2593  count = WINED3D_MAX_CONSTS_B - start_idx;
2594  memcpy(&device->update_state->ps_consts_b[start_idx], constants, count * sizeof(*constants));
2595  if (TRACE_ON(d3d))
2596  {
2597  for (i = 0; i < count; ++i)
2598  TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]);
2599  }
2600 
2601  if (device->recording)
2602  {
2603  for (i = start_idx; i < count + start_idx; ++i)
2604  device->recording->changed.pixelShaderConstantsB |= (1u << i);
2605  }
2606  else
2607  {
2609  }
2610 
2611  return WINED3D_OK;
2612 }
2613 
2615  unsigned int start_idx, unsigned int count, BOOL *constants)
2616 {
2617  TRACE("device %p, start_idx %u, count %u,constants %p.\n",
2618  device, start_idx, count, constants);
2619 
2620  if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
2621  return WINED3DERR_INVALIDCALL;
2622 
2623  if (count > WINED3D_MAX_CONSTS_B - start_idx)
2624  count = WINED3D_MAX_CONSTS_B - start_idx;
2625  memcpy(constants, &device->state.ps_consts_b[start_idx], count * sizeof(*constants));
2626 
2627  return WINED3D_OK;
2628 }
2629 
2631  unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants)
2632 {
2633  unsigned int i;
2634 
2635  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2636  device, start_idx, count, constants);
2637 
2638  if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
2639  return WINED3DERR_INVALIDCALL;
2640 
2641  if (count > WINED3D_MAX_CONSTS_I - start_idx)
2642  count = WINED3D_MAX_CONSTS_I - start_idx;
2643  memcpy(&device->update_state->ps_consts_i[start_idx], constants, count * sizeof(*constants));
2644  if (TRACE_ON(d3d))
2645  {
2646  for (i = 0; i < count; ++i)
2647  TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i]));
2648  }
2649 
2650  if (device->recording)
2651  {
2652  for (i = start_idx; i < count + start_idx; ++i)
2653  device->recording->changed.pixelShaderConstantsI |= (1u << i);
2654  }
2655  else
2656  {
2658  }
2659 
2660  return WINED3D_OK;
2661 }
2662 
2664  unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants)
2665 {
2666  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2667  device, start_idx, count, constants);
2668 
2669  if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
2670  return WINED3DERR_INVALIDCALL;
2671 
2672  if (count > WINED3D_MAX_CONSTS_I - start_idx)
2673  count = WINED3D_MAX_CONSTS_I - start_idx;
2674  memcpy(constants, &device->state.ps_consts_i[start_idx], count * sizeof(*constants));
2675 
2676  return WINED3D_OK;
2677 }
2678 
2680  unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants)
2681 {
2682  const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
2683  unsigned int i;
2684 
2685  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2686  device, start_idx, count, constants);
2687 
2688  if (!constants || start_idx >= d3d_info->limits.ps_uniform_count
2689  || count > d3d_info->limits.ps_uniform_count - start_idx)
2690  return WINED3DERR_INVALIDCALL;
2691 
2692  memcpy(&device->update_state->ps_consts_f[start_idx], constants, count * sizeof(*constants));
2693  if (TRACE_ON(d3d))
2694  {
2695  for (i = 0; i < count; ++i)
2696  TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i]));
2697  }
2698 
2699  if (device->recording)
2700  memset(&device->recording->changed.ps_consts_f[start_idx], 1,
2701  count * sizeof(*device->recording->changed.ps_consts_f));
2702  else
2704 
2705  return WINED3D_OK;
2706 }
2707 
2709  unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants)
2710 {
2711  const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
2712 
2713  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2714  device, start_idx, count, constants);
2715 
2716  if (!constants || start_idx >= d3d_info->limits.ps_uniform_count
2717  || count > d3d_info->limits.ps_uniform_count - start_idx)
2718  return WINED3DERR_INVALIDCALL;
2719 
2720  memcpy(constants, &device->state.ps_consts_f[start_idx], count * sizeof(*constants));
2721 
2722  return WINED3D_OK;
2723 }
2724 
2726 {
2727  struct wined3d_shader *prev;
2728 
2729  TRACE("device %p, shader %p.\n", device, shader);
2730 
2731  prev = device->update_state->shader[WINED3D_SHADER_TYPE_HULL];
2732  if (shader == prev)
2733  return;
2734  if (shader)
2736  device->update_state->shader[WINED3D_SHADER_TYPE_HULL] = shader;
2738  if (prev)
2739  wined3d_shader_decref(prev);
2740 }
2741 
2743 {
2744  TRACE("device %p.\n", device);
2745 
2746  return device->state.shader[WINED3D_SHADER_TYPE_HULL];
2747 }
2748 
2750 {
2751  TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2752 
2754 }
2755 
2757 {
2758  TRACE("device %p, idx %u.\n", device, idx);
2759 
2761 }
2762 
2764  unsigned int idx, struct wined3d_shader_resource_view *view)
2765 {
2766  TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2767 
2769 }
2770 
2772  unsigned int idx)
2773 {
2774  TRACE("device %p, idx %u.\n", device, idx);
2775 
2777 }
2778 
2780  unsigned int idx, struct wined3d_sampler *sampler)
2781 {
2782  TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2783 
2785 }
2786 
2788 {
2789  TRACE("device %p, idx %u.\n", device, idx);
2790 
2792 }
2793 
2795 {
2796  struct wined3d_shader *prev;
2797 
2798  TRACE("device %p, shader %p.\n", device, shader);
2799 
2800  prev = device->update_state->shader[WINED3D_SHADER_TYPE_DOMAIN];
2801  if (shader == prev)
2802  return;
2803  if (shader)
2805  device->update_state->shader[WINED3D_SHADER_TYPE_DOMAIN] = shader;
2807  if (prev)
2808  wined3d_shader_decref(prev);
2809 }
2810 
2812 {
2813  TRACE("device %p.\n", device);
2814 
2815  return device->state.shader[WINED3D_SHADER_TYPE_DOMAIN];
2816 }
2817 
2819 {
2820  TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2821 
2823 }
2824 
2826 {
2827  TRACE("device %p, idx %u.\n", device, idx);
2828 
2830 }
2831 
2833  unsigned int idx, struct wined3d_shader_resource_view *view)
2834 {
2835  TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2836 
2838 }
2839 
2841  unsigned int idx)
2842 {
2843  TRACE("device %p, idx %u.\n", device, idx);
2844 
2846 }
2847 
2849  unsigned int idx, struct wined3d_sampler *sampler)
2850 {
2851  TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2852 
2854 }
2855 
2857 {
2858  TRACE("device %p, idx %u.\n", device, idx);
2859 
2861 }
2862 
2864 {
2865  struct wined3d_shader *prev = device->update_state->shader[WINED3D_SHADER_TYPE_GEOMETRY];
2866 
2867  TRACE("device %p, shader %p.\n", device, shader);
2868 
2869  if (device->recording || shader == prev)
2870  return;
2871  if (shader)
2873  device->update_state->shader[WINED3D_SHADER_TYPE_GEOMETRY] = shader;
2875  if (prev)
2876  wined3d_shader_decref(prev);
2877 }
2878 
2880 {
2881  TRACE("device %p.\n", device);
2882 
2883  return device->state.shader[WINED3D_SHADER_TYPE_GEOMETRY];
2884 }
2885 
2887 {
2888  TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2889 
2891 }
2892 
2894 {
2895  TRACE("device %p, idx %u.\n", device, idx);
2896 
2898 }
2899 
2902 {
2903  TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2904 
2906 }
2907 
2909  UINT idx)
2910 {
2911  TRACE("device %p, idx %u.\n", device, idx);
2912 
2914 }
2915 
2917 {
2918  TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2919 
2921 }
2922 
2924 {
2925  TRACE("device %p, idx %u.\n", device, idx);
2926 
2928 }
2929 
2931 {
2932  struct wined3d_shader *prev;
2933 
2934  TRACE("device %p, shader %p.\n", device, shader);
2935 
2936  prev = device->update_state->shader[WINED3D_SHADER_TYPE_COMPUTE];
2937  if (device->recording || shader == prev)
2938  return;
2939  if (shader)
2941  device->update_state->shader[WINED3D_SHADER_TYPE_COMPUTE] = shader;
2943  if (prev)
2944  wined3d_shader_decref(prev);
2945 }
2946 
2948 {
2949  TRACE("device %p.\n", device);
2950 
2951  return device->state.shader[WINED3D_SHADER_TYPE_COMPUTE];
2952 }
2953 
2955 {
2956  TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2957 
2959 }
2960 
2962 {
2963  TRACE("device %p, idx %u.\n", device, idx);
2964 
2966 }
2967 
2969  unsigned int idx, struct wined3d_shader_resource_view *view)
2970 {
2971  TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2972 
2974 }
2975 
2977  unsigned int idx)
2978 {
2979  TRACE("device %p, idx %u.\n", device, idx);
2980 
2982 }
2983 
2985  unsigned int idx, struct wined3d_sampler *sampler)
2986 {
2987  TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2988 
2990 }
2991 
2993 {
2994  TRACE("device %p, idx %u.\n", device, idx);
2995 
2997 }
2998 
3000  enum wined3d_pipeline pipeline, unsigned int idx, struct wined3d_unordered_access_view *uav,
3001  unsigned int initial_count)
3002 {
3003  struct wined3d_unordered_access_view *prev;
3004 
3006  {
3007  WARN("Invalid UAV index %u.\n", idx);
3008  return;
3009  }
3010 
3011  prev = device->update_state->unordered_access_view[pipeline][idx];
3012  if (uav == prev && initial_count == ~0u)
3013  return;
3014 
3015  if (uav)
3017  device->update_state->unordered_access_view[pipeline][idx] = uav;
3018  if (!device->recording)
3019  wined3d_cs_emit_set_unordered_access_view(device->cs, pipeline, idx, uav, initial_count);
3020  if (prev)
3022 }
3023 
3025  const struct wined3d_device *device, enum wined3d_pipeline pipeline, unsigned int idx)
3026 {
3028  {
3029  WARN("Invalid UAV index %u.\n", idx);
3030  return NULL;
3031  }
3032 
3033  return device->state.unordered_access_view[pipeline][idx];
3034 }
3035 
3037  struct wined3d_unordered_access_view *uav, unsigned int initial_count)
3038 {
3039  TRACE("device %p, idx %u, uav %p, initial_count %#x.\n", device, idx, uav, initial_count);
3040 
3042 }
3043 
3045  unsigned int idx)
3046 {
3047  TRACE("device %p, idx %u.\n", device, idx);
3048 
3050 }
3051 
3053  unsigned int idx, struct wined3d_unordered_access_view *uav, unsigned int initial_count)
3054 {
3055  TRACE("device %p, idx %u, uav %p, initial_count %#x.\n", device, idx, uav, initial_count);
3056 
3058 }
3059 
3061  const struct wined3d_device *device, unsigned int idx)
3062 {
3063  TRACE("device %p, idx %u.\n", device, idx);
3064 
3066 }
3067 
3068 /* Context activation is done by the caller. */
3069 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3070 static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount,
3072  DWORD DestFVF)
3073 {
3074  struct wined3d_matrix mat, proj_mat, view_mat, world_mat;
3075  struct wined3d_map_desc map_desc;
3076  struct wined3d_box box = {0};
3077  struct wined3d_viewport vp;
3078  UINT vertex_size;
3079  unsigned int i;
3080  BYTE *dest_ptr;
3081  BOOL doClip;
3082  DWORD numTextures;
3083  HRESULT hr;
3084 
3085  if (stream_info->use_map & (1u << WINED3D_FFP_NORMAL))
3086  {
3087  WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3088  }
3089 
3090  if (!(stream_info->use_map & (1u << WINED3D_FFP_POSITION)))
3091  {
3092  ERR("Source has no position mask\n");
3093  return WINED3DERR_INVALIDCALL;
3094  }
3095 
3096  if (device->state.render_states[WINED3D_RS_CLIPPING])
3097  {
3098  static BOOL warned = FALSE;
3099  /*
3100  * The clipping code is not quite correct. Some things need
3101  * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3102  * so disable clipping for now.
3103  * (The graphics in Half-Life are broken, and my processvertices
3104  * test crashes with IDirect3DDevice3)
3105  doClip = TRUE;
3106  */
3107  doClip = FALSE;
3108  if(!warned) {
3109  warned = TRUE;
3110  FIXME("Clipping is broken and disabled for now\n");
3111  }
3112  }
3113  else
3114  doClip = FALSE;
3115 
3116  vertex_size = get_flexible_vertex_size(DestFVF);
3117  box.left = dwDestIndex * vertex_size;
3118  box.right = box.left + dwCount * vertex_size;
3119  if (FAILED(hr = wined3d_resource_map(&dest->resource, 0, &map_desc, &box, WINED3D_MAP_WRITE)))
3120  {
3121  WARN("Failed to map buffer, hr %#x.\n", hr);
3122  return hr;
3123  }
3124  dest_ptr = map_desc.data;
3125 
3129 
3130  TRACE("View mat:\n");
3131  TRACE("%.8e %.8e %.8e %.8e\n", view_mat._11, view_mat._12, view_mat._13, view_mat._14);
3132  TRACE("%.8e %.8e %.8e %.8e\n", view_mat._21, view_mat._22, view_mat._23, view_mat._24);
3133  TRACE("%.8e %.8e %.8e %.8e\n", view_mat._31, view_mat._32, view_mat._33, view_mat._34);
3134  TRACE("%.8e %.8e %.8e %.8e\n", view_mat._41, view_mat._42, view_mat._43, view_mat._44);
3135 
3136  TRACE("Proj mat:\n");
3137  TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._11, proj_mat._12, proj_mat._13, proj_mat._14);
3138  TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._21, proj_mat._22, proj_mat._23, proj_mat._24);
3139  TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._31, proj_mat._32, proj_mat._33, proj_mat._34);
3140  TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._41, proj_mat._42, proj_mat._43, proj_mat._44);
3141 
3142  TRACE("World mat:\n");
3143  TRACE("%.8e %.8e %.8e %.8e\n", world_mat._11, world_mat._12, world_mat._13, world_mat._14);
3144  TRACE("%.8e %.8e %.8e %.8e\n", world_mat._21, world_mat._22, world_mat._23, world_mat._24);
3145  TRACE("%.8e %.8e %.8e %.8e\n", world_mat._31, world_mat._32, world_mat._33, world_mat._34);
3146  TRACE("%.8e %.8e %.8e %.8e\n", world_mat._41, world_mat._42, world_mat._43, world_mat._44);
3147 
3148  /* Get the viewport */
3150  TRACE("viewport x %.8e, y %.8e, width %.8e, height %.8e, min_z %.8e, max_z %.8e.\n",
3151  vp.x, vp.y, vp.width, vp.height, vp.min_z, vp.max_z);
3152 
3153  multiply_matrix(&mat,&view_mat,&world_mat);
3154  multiply_matrix(&mat,&proj_mat,&mat);
3155 
3156  numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3157 
3158  for (i = 0; i < dwCount; i+= 1) {
3159  unsigned int tex_index;
3160 
3161  if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3162  ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3163  /* The position first */
3165  const float *p = (const float *)(element->data.addr + i * element->stride);
3166  float x, y, z, rhw;
3167  TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3168 
3169  /* Multiplication with world, view and projection matrix. */
3170  x = (p[0] * mat._11) + (p[1] * mat._21) + (p[2] * mat._31) + mat._41;
3171  y = (p[0] * mat._12) + (p[1] * mat._22) + (p[2] * mat._32) + mat._42;
3172  z = (p[0] * mat._13) + (p[1] * mat._23) + (p[2] * mat._33) + mat._43;
3173  rhw = (p[0] * mat._14) + (p[1] * mat._24) + (p[2] * mat._34) + mat._44;
3174 
3175  TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3176 
3177  /* WARNING: The following things are taken from d3d7 and were not yet checked
3178  * against d3d8 or d3d9!
3179  */
3180 
3181  /* Clipping conditions: From msdn
3182  *
3183  * A vertex is clipped if it does not match the following requirements
3184  * -rhw < x <= rhw
3185  * -rhw < y <= rhw
3186  * 0 < z <= rhw
3187  * 0 < rhw ( Not in d3d7, but tested in d3d7)
3188  *
3189  * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3190  * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3191  *
3192  */
3193 
3194  if( !doClip ||
3195  ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3196  (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
3197  ( rhw > eps ) ) ) {
3198 
3199  /* "Normal" viewport transformation (not clipped)
3200  * 1) The values are divided by rhw
3201  * 2) The y axis is negative, so multiply it with -1
3202  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3203  * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3204  * 4) Multiply x with Width/2 and add Width/2
3205  * 5) The same for the height
3206  * 6) Add the viewpoint X and Y to the 2D coordinates and
3207  * The minimum Z value to z
3208  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3209  *
3210  * Well, basically it's simply a linear transformation into viewport
3211  * coordinates
3212  */
3213 
3214  x /= rhw;
3215  y /= rhw;
3216  z /= rhw;
3217 
3218  y *= -1;
3219 
3220  x *= vp.width / 2;
3221  y *= vp.height / 2;
3222  z *= vp.max_z - vp.min_z;
3223 
3224  x += vp.width / 2 + vp.x;
3225  y += vp.height / 2 + vp.y;
3226  z += vp.min_z;
3227 
3228  rhw = 1 / rhw;
3229  } else {
3230  /* That vertex got clipped
3231  * Contrary to OpenGL it is not dropped completely, it just
3232  * undergoes a different calculation.
3233  */
3234  TRACE("Vertex got clipped\n");
3235  x += rhw;
3236  y += rhw;
3237 
3238  x /= 2;
3239  y /= 2;
3240 
3241  /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3242  * outside of the main vertex buffer memory. That needs some more
3243  * investigation...
3244  */
3245  }
3246 
3247  TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3248 
3249 
3250  ( (float *) dest_ptr)[0] = x;
3251  ( (float *) dest_ptr)[1] = y;
3252  ( (float *) dest_ptr)[2] = z;
3253  ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3254 
3255  dest_ptr += 3 * sizeof(float);
3256 
3257  if ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW)
3258  dest_ptr += sizeof(float);
3259  }
3260 
3261  if (DestFVF & WINED3DFVF_PSIZE)
3262  dest_ptr += sizeof(DWORD);
3263 
3264  if (DestFVF & WINED3DFVF_NORMAL)
3265  {
3267  const float *normal = (const float *)(element->data.addr + i * element->stride);
3268  /* AFAIK this should go into the lighting information */
3269  FIXME("Didn't expect the destination to have a normal\n");
3270  copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3271  }
3272 
3273  if (DestFVF & WINED3DFVF_DIFFUSE)
3274  {
3276  const DWORD *color_d = (const DWORD *)(element->data.addr + i * element->stride);
3277  if (!(stream_info->use_map & (1u << WINED3D_FFP_DIFFUSE)))
3278  {
3279  static BOOL warned = FALSE;
3280 
3281  if(!warned) {
3282  ERR("No diffuse color in source, but destination has one\n");
3283  warned = TRUE;
3284  }
3285 
3286  *( (DWORD *) dest_ptr) = 0xffffffff;
3287  dest_ptr += sizeof(DWORD);
3288  }
3289  else
3290  {
3291  copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3292  }
3293  }
3294 
3295  if (DestFVF & WINED3DFVF_SPECULAR)
3296  {
3297  /* What's the color value in the feedback buffer? */
3299  const DWORD *color_s = (const DWORD *)(element->data.addr + i * element->stride);
3300  if (!(stream_info->use_map & (1u << WINED3D_FFP_SPECULAR)))
3301  {
3302  static BOOL warned = FALSE;
3303 
3304  if(!warned) {
3305  ERR("No specular color in source, but destination has one\n");
3306  warned = TRUE;
3307  }
3308 
3309  *(DWORD *)dest_ptr = 0xff000000;
3310  dest_ptr += sizeof(DWORD);
3311  }
3312  else
3313  {
3314  copy_and_next(dest_ptr, color_s, sizeof(DWORD));
3315  }
3316  }
3317 
3318  for (tex_index = 0; tex_index < numTextures; ++tex_index)
3319  {
3320  const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_TEXCOORD0 + tex_index];
3321  const float *tex_coord = (const float *)(element->data.addr + i * element->stride);
3322  if (!(stream_info->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + tex_index))))
3323  {
3324  ERR("No source texture, but destination requests one\n");
3325  dest_ptr += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3326  }
3327  else
3328  {
3329  copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3330  }
3331  }
3332  }
3333 
3334  wined3d_resource_unmap(&dest->resource, 0);
3335 
3336  return WINED3D_OK;
3337 }
3338 #undef copy_and_next
3339 
3341  UINT src_start_idx, UINT dst_idx, UINT vertex_count, struct wined3d_buffer *dst_buffer,
3342  const struct wined3d_vertex_declaration *declaration, DWORD flags, DWORD dst_fvf)
3343 {
3344  struct wined3d_state *state = &device->state;
3346  struct wined3d_resource *resource;
3347  struct wined3d_box box = {0};
3348  struct wined3d_shader *vs;
3349  unsigned int i;
3350  HRESULT hr;
3351  WORD map;
3352 
3353  TRACE("device %p, src_start_idx %u, dst_idx %u, vertex_count %u, "
3354  "dst_buffer %p, declaration %p, flags %#x, dst_fvf %#x.\n",
3355  device, src_start_idx, dst_idx, vertex_count,
3356  dst_buffer, declaration, flags, dst_fvf);
3357 
3358  if (declaration)
3359  FIXME("Output vertex declaration not implemented yet.\n");
3360 
3361  vs = state->shader[WINED3D_SHADER_TYPE_VERTEX];
3363  wined3d_stream_info_from_declaration(&stream_info, state, &device->adapter->gl_info, &device->adapter->d3d_info);
3364  state->shader[WINED3D_SHADER_TYPE_VERTEX] = vs;
3365 
3366  /* We can't convert FROM a VBO, and vertex buffers used to source into
3367  * process_vertices() are unlikely to ever be used for drawing. Release
3368  * VBOs in those buffers and fix up the stream_info structure.
3369  *
3370  * Also apply the start index. */
3371  for (i = 0, map = stream_info.use_map; map; map >>= 1, ++i)
3372  {
3374  struct wined3d_map_desc map_desc;
3375 
3376  if (!(map & 1))
3377  continue;
3378 
3379  e = &stream_info.elements[i];
3380  resource = &state->streams[e->stream_idx].buffer->resource;
3381  box.left = src_start_idx * e->stride;
3382  box.right = box.left + vertex_count * e->stride;
3383  if (FAILED(wined3d_resource_map(resource, 0, &map_desc, &box, WINED3D_MAP_READ)))
3384  ERR("Failed to map resource.\n");
3385  e->data.buffer_object = 0;
3386  e->data.addr += (ULONG_PTR)map_desc.data;
3387  }
3388 
3390  &stream_info, dst_buffer, flags, dst_fvf);
3391 
3392  for (i = 0, map = stream_info.use_map; map; map >>= 1, ++i)
3393  {
3394  if (!(map & 1))
3395  continue;
3396 
3397  resource = &state->streams[stream_info.elements[i].stream_idx].buffer->resource;
3399  ERR("Failed to unmap resource.\n");
3400  }
3401 
3402  return hr;
3403 }
3404 
3407 {
3408  const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
3409  DWORD old_value;
3410 
3411  TRACE("device %p, stage %u, state %s, value %#x.\n",
3413 
3415  {
3416  WARN("Invalid state %#x passed.\n", state);
3417  return;
3418  }
3419 
3420  if (stage >= d3d_info->limits.ffp_blend_stages)
3421  {
3422  WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n",
3423  stage, d3d_info->limits.ffp_blend_stages - 1);
3424  return;
3425  }
3426 
3427  old_value = device->update_state->texture_states[stage][state];
3428  device->update_state->texture_states[stage][state] = value;
3429 
3430  if (device->recording)
3431  {
3432  TRACE("Recording... not performing anything.\n");
3433  device->recording->changed.textureState[stage] |= 1u << state;
3434  return;
3435  }
3436 
3437  /* Checked after the assignments to allow proper stateblock recording. */
3438  if (old_value == value)
3439  {
3440  TRACE("Application is setting the old value over, nothing to do.\n");
3441  return;
3442  }
3443 
3445 }
3446 
3449 {
3450  TRACE("device %p, stage %u, state %s.\n",
3452 
3454  {
3455  WARN("Invalid state %#x passed.\n", state);
3456  return 0;
3457  }
3458 
3459  return device->state.texture_states[stage][state];
3460 }
3461 
3463  UINT stage, struct wined3d_texture *texture)
3464 {
3465  struct wined3d_texture *prev;
3466 
3467  TRACE("device %p, stage %u, texture %p.\n", device, stage, texture);
3468 
3471 
3472  /* Windows accepts overflowing this array... we do not. */
3473  if (stage >= ARRAY_SIZE(device->state.textures))
3474  {
3475  WARN("Ignoring invalid stage %u.\n", stage);
3476  return WINED3D_OK;
3477  }
3478 
3479  if (texture && texture->resource.usage & WINED3DUSAGE_SCRATCH)
3480  {
3481  WARN("Rejecting attempt to set scratch texture.\n");
3482  return WINED3DERR_INVALIDCALL;
3483  }
3484 
3485  if (device->recording)
3486  device->recording->changed.textures |= 1u << stage;
3487 
3488  prev = device->update_state->textures[stage];
3489  TRACE("Previous texture %p.\n", prev);
3490 
3491  if (texture == prev)
3492  {
3493  TRACE("App is setting the same texture again, nothing to do.\n");
3494  return WINED3D_OK;
3495  }
3496 
3497  TRACE("Setting new texture to %p.\n", texture);
3498  device->update_state->textures[stage] = texture;
3499 
3500  if (texture)
3502  if (!device->recording)
3504  if (prev)
3505  wined3d_texture_decref(prev);
3506 
3507  return WINED3D_OK;
3508 }
3509 
3511 {
3512  TRACE("device %p, stage %u.\n", device, stage);
3513 
3516 
3517  if (stage >= ARRAY_SIZE(device->state.textures))
3518  {
3519  WARN("Ignoring invalid stage %u.\n", stage);
3520  return NULL; /* Windows accepts overflowing this array ... we do not. */
3521  }
3522 
3523  return device->state.textures[stage];
3524 }
3525 
3527 {
3528  HRESULT hr;
3529 
3530  TRACE("device %p, caps %p.\n", device, caps);
3531 
3532  hr = wined3d_get_device_caps(device->wined3d, device->adapter->ordinal,
3533  device->create_parms.device_type, caps);
3534 
3536  caps->MaxVertexBlendMatrixIndex = 255;
3537 
3538  return hr;
3539 }
3540 
3542  struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation)
3543 {
3544  struct wined3d_swapchain *swapchain;
3545 
3546  TRACE("device %p, swapchain_idx %u, mode %p, rotation %p.\n",
3547  device, swapchain_idx, mode, rotation);
3548 
3549  if (!(swapchain = wined3d_device_get_swapchain(device, swapchain_idx)))
3550  return WINED3DERR_INVALIDCALL;
3551 
3552  return wined3d_swapchain_get_display_mode(swapchain, mode, rotation);
3553 }
3554 
3556 {
3557  struct wined3d_stateblock *stateblock;
3558  HRESULT hr;
3559 
3560  TRACE("device %p.\n", device);
3561 
3562  if (device->recording)
3563  return WINED3DERR_INVALIDCALL;
3564 
3566  if (FAILED(hr))
3567  return hr;
3568 
3569  device->recording = stateblock;
3570  device->update_state = &stateblock->state;
3571 
3572  TRACE("Recording stateblock %p.\n", stateblock);
3573 
3574  return WINED3D_OK;
3575 }
3576 
3578  struct wined3d_stateblock **stateblock)
3579 {
3580  struct wined3d_stateblock *object = device->recording;
3581 
3582  TRACE("device %p, stateblock %p.\n", device, stateblock);
3583 
3584  if (!device->recording)
3585  {
3586  WARN("Not recording.\n");
3587  *stateblock = NULL;
3588  return WINED3DERR_INVALIDCALL;
3589  }
3590 
3592 
3593  *stateblock = object;
3594  device->recording = NULL;
3595  device->update_state = &device->state;
3596 
3597  TRACE("Returning stateblock %p.\n", *stateblock);
3598 
3599  return WINED3D_OK;
3600 }
3601 
3603 {
3604  /* At the moment we have no need for any functionality at the beginning
3605  * of a scene. */
3606  TRACE("device %p.\n", device);
3607 
3608  if (device->inScene)
3609  {
3610  WARN("Already in scene, returning WINED3DERR_INVALIDCALL.\n");
3611  return WINED3DERR_INVALIDCALL;
3612  }
3613  device->inScene = TRUE;
3614  return WINED3D_OK;
3615 }
3616 
3618 {
3619  TRACE("device %p.\n", device);
3620 
3621  if (!device->inScene)
3622  {
3623  WARN("Not in scene, returning WINED3DERR_INVALIDCALL.\n");
3624  return WINED3DERR_INVALIDCALL;
3625  }
3626 
3628 
3629  device->inScene = FALSE;
3630  return WINED3D_OK;
3631 }
3632 
3634  const RECT *rects, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil)
3635 {
3636  TRACE("device %p, rect_count %u, rects %p, flags %#x, color %s, depth %.8e, stencil %u.\n",
3637  device, rect_count, rects, flags, debug_color(color), depth, stencil);
3638 
3639  if (!rect_count && rects)
3640  {
3641  WARN("Rects is %p, but rect_count is 0, ignoring clear\n", rects);
3642  return WINED3D_OK;
3643  }
3644 
3646  {
3647  struct wined3d_rendertarget_view *ds = device->fb.depth_stencil;
3648  if (!ds)
3649  {
3650  WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
3651  /* TODO: What about depth stencil buffers without stencil bits? */
3652  return WINED3DERR_INVALIDCALL;
3653  }
3654  else if (flags & WINED3DCLEAR_TARGET)
3655  {
3656  if (ds->width < device->fb.render_targets[0]->width
3657  || ds->height < device->fb.render_targets[0]->height)
3658  {
3659  WARN("Silently ignoring depth and target clear with mismatching sizes\n");
3660  return WINED3D_OK;
3661  }
3662  }
3663  }
3664 
3665  wined3d_cs_emit_clear(device->cs, rect_count, rects, flags, color, depth, stencil);
3666 
3667  return WINED3D_OK;
3668 }
3669 
3671  struct wined3d_query *predicate, BOOL value)
3672 {
3673  struct wined3d_query *prev;
3674 
3675  TRACE("device %p, predicate %p, value %#x.\n", device, predicate, value);
3676 
3677  prev = device->update_state->predicate;
3678  if (predicate)
3679  {
3680  FIXME("Predicated rendering not implemented.\n");
3681  wined3d_query_incref(predicate);
3682  }
3683  device->update_state->predicate = predicate;
3684  device->update_state->predicate_value = value;
3685  if (!device->recording)
3686  wined3d_cs_emit_set_predication(device->cs, predicate, value);
3687  if (prev)
3688  wined3d_query_decref(prev);
3689 }
3690 
3692 {
3693  TRACE("device %p, value %p.\n", device, value);
3694 
3695  if (value)
3696  *value = device->state.predicate_value;
3697  return device->state.predicate;
3698 }
3699 
3701  unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z)
3702 {
3703  TRACE("device %p, group_count_x %u, group_count_y %u, group_count_z %u.\n",
3704  device, group_count_x, group_count_y, group_count_z);
3705 
3706  wined3d_cs_emit_dispatch(device->cs, group_count_x, group_count_y, group_count_z);
3707 }
3708 
3710  struct wined3d_buffer *buffer, unsigned int offset)
3711 {
3712  TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset);
3713 
3715 }
3716 
3718  enum wined3d_primitive_type primitive_type, unsigned int patch_vertex_count)
3719 {
3720  TRACE("device %p, primitive_type %s, patch_vertex_count %u.\n",
3721  device, debug_d3dprimitivetype(primitive_type), patch_vertex_count);
3722 
3723  device->state.gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
3724  device->state.gl_patch_vertices = patch_vertex_count;
3725 }
3726 
3728  enum wined3d_primitive_type *primitive_type, unsigned int *patch_vertex_count)
3729 {
3730  TRACE("device %p, primitive_type %p, patch_vertex_count %p.\n",
3731  device, primitive_type, patch_vertex_count);
3732 
3733  *primitive_type = d3d_primitive_type_from_gl(device->state.gl_primitive_type);
3734  if (patch_vertex_count)
3735  *patch_vertex_count = device->state.gl_patch_vertices;
3736 
3737  TRACE("Returning %s.\n", debug_d3dprimitivetype(*primitive_type));
3738 }
3739 
3741 {
3742  TRACE("device %p, start_vertex %u, vertex_count %u.\n", device, start_vertex, vertex_count);
3743 
3744  wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
3745  0, start_vertex, vertex_count, 0, 0, FALSE);
3746 
3747  return WINED3D_OK;
3748 }
3749 
3751  UINT start_vertex, UINT vertex_count, UINT start_instance, UINT instance_count)
3752 {
3753  TRACE("device %p, start_vertex %u, vertex_count %u, start_instance %u, instance_count %u.\n",
3754  device, start_vertex, vertex_count, start_instance, instance_count);
3755 
3756  wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
3757  0, start_vertex, vertex_count, start_instance, instance_count, FALSE);
3758 }
3759 
3761  struct wined3d_buffer *buffer, unsigned int offset)
3762 {
3763  TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset);
3764 
3765  wined3d_cs_emit_draw_indirect(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
3766  buffer, offset, FALSE);
3767 }
3768 
3770 {
3771  TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count);
3772 
3773  if (!device->state.index_buffer)
3774  {
3775  /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
3776  * without an index buffer set. (The first time at least...)
3777  * D3D8 simply dies, but I doubt it can do much harm to return
3778  * D3DERR_INVALIDCALL there as well. */
3779  WARN("Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL.\n");
3780  return WINED3DERR_INVALIDCALL;
3781  }
3782 
3783  wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
3784  device->state.base_vertex_index, start_idx, index_count, 0, 0, TRUE);
3785 
3786  return WINED3D_OK;
3787 }
3788 
3790  UINT start_idx, UINT index_count, UINT start_instance, UINT instance_count)
3791 {
3792  TRACE("device %p, start_idx %u, index_count %u, start_instance %u, instance_count %u.\n",
3793  device, start_idx, index_count, start_instance, instance_count);
3794 
3795  wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
3796  device->state.base_vertex_index, start_idx, index_count, start_instance, instance_count, TRUE);
3797 }
3798 
3800  struct wined3d_buffer *buffer, unsigned int offset)
3801 {
3802  TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset);
3803 
3804  wined3d_cs_emit_draw_indirect(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
3805  buffer, offset, TRUE);
3806 }
3807 
3809  struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture)
3810 {
3811  unsigned int src_size, dst_size, src_skip_levels = 0;
3812  unsigned int src_level_count, dst_level_count;
3813  unsigned int layer_count, level_count, i, j;
3814  unsigned int width, height, depth;
3816  struct wined3d_box box;
3817 
3818  TRACE("device %p, src_texture %p, dst_texture %p.\n", device, src_texture, dst_texture);
3819 
3820  /* Verify that the source and destination textures are non-NULL. */
3821  if (!src_texture || !dst_texture)
3822  {
3823  WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n");
3824  return WINED3DERR_INVALIDCALL;
3825  }
3826 
3827  if (src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU
3828  || src_texture->resource.usage & WINED3DUSAGE_SCRATCH)
3829  {
3830  WARN("Source resource is GPU accessible or a scratch resource.\n");
3831  return WINED3DERR_INVALIDCALL;
3832  }
3833  if (dst_texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU)
3834  {
3835  WARN("Destination resource is CPU accessible.\n");
3836  return WINED3DERR_INVALIDCALL;
3837  }
3838 
3839  /* Verify that the source and destination textures are the same type. */
3840  type = src_texture->resource.type;
3841  if (dst_texture->resource.type != type)
3842  {
3843  WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n");
3844  return WINED3DERR_INVALIDCALL;
3845  }
3846 
3847  layer_count = src_texture->layer_count;
3848  if (layer_count != dst_texture->layer_count)
3849  {
3850  WARN("Source and destination have different layer counts.\n");
3851  return WINED3DERR_INVALIDCALL;
3852  }
3853 
3854  if (src_texture->resource.format != dst_texture->resource.format)
3855  {
3856  WARN("Source and destination formats do not match.\n");
3857  return WINED3DERR_INVALIDCALL;
3858  }
3859 
3860  src_level_count = src_texture->level_count;
3861  dst_level_count = dst_texture->level_count;
3862  level_count = min(src_level_count, dst_level_count);
3863 
3864  src_size = max(src_texture->resource.width, src_texture->resource.height);
3865  dst_size = max(dst_texture->resource.width, dst_texture->resource.height);
3867  {
3868  src_size = max(src_size, src_texture->resource.depth);
3869  dst_size = max(dst_size, dst_texture->resource.depth);
3870  }
3871  while (src_size > dst_size)
3872  {
3873  src_size >>= 1;
3874  ++src_skip_levels;
3875  }
3876 
3877  if (wined3d_texture_get_level_width(src_texture, src_skip_levels) != dst_texture->resource.width
3878  || wined3d_texture_get_level_height(src_texture, src_skip_levels) != dst_texture->resource.height
3879  || wined3d_texture_get_level_depth(src_texture, src_skip_levels) != dst_texture->resource.depth)
3880  {
3881  WARN("Source and destination dimensions do not match.\n");
3882  return WINED3DERR_INVALIDCALL;
3883  }
3884 
3885  /* Update every surface level of the texture. */
3886  for (i = 0; i < level_count; ++i)
3887  {
3888  width = wined3d_texture_get_level_width(dst_texture, i);
3889  height = wined3d_texture_get_level_height(dst_texture, i);
3890  depth = wined3d_texture_get_level_depth(dst_texture, i);
3891  wined3d_box_set(&box, 0, 0, width, height, 0, depth);
3892 
3893  for (j = 0; j < layer_count; ++j)
3894  {
3896  &dst_texture->resource, j * dst_level_count + i, &box,
3897  &src_texture->resource, j * src_level_count + i + src_skip_levels, &box,
3898  0, NULL, WINED3D_TEXF_POINT);
3899  }
3900  }
3901 
3902  return WINED3D_OK;
3903 }
3904 
3906 {
3907  const struct wined3d_state *state = &device->state;
3908  struct wined3d_texture *texture;
3909  DWORD i;
3910 
3911  TRACE("device %p, num_passes %p.\n", device, num_passes);
3912 
3913  for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
3914  {
3915  if (state->sampler_states[i][WINED3D_SAMP_MIN_FILTER] == WINED3D_TEXF_NONE)
3916  {
3917  WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
3919  }
3920  if (state->sampler_states[i][WINED3D_SAMP_MAG_FILTER] == WINED3D_TEXF_NONE)
3921  {
3922  WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
3924  }
3925 
3926  texture = state->textures[i];
3927  if (!texture || texture->resource.format_flags & WINED3DFMT_FLAG_FILTERING) continue;
3928 
3929  if (state->sampler_states[i][WINED3D_SAMP_MAG_FILTER] != WINED3D_TEXF_POINT)
3930  {
3931  WARN("Non-filterable texture and mag filter enabled on sampler %u, returning E_FAIL\n", i);
3932  return E_FAIL;
3933  }
3934  if (state->sampler_states[i][WINED3D_SAMP_MIN_FILTER] != WINED3D_TEXF_POINT)
3935  {
3936  WARN("Non-filterable texture and min filter enabled on sampler %u, returning E_FAIL\n", i);
3937  return E_FAIL;
3938  }
3939  if (state->sampler_states[i][WINED3D_SAMP_MIP_FILTER] != WINED3D_TEXF_NONE
3940  && state->sampler_states[i][WINED3D_SAMP_MIP_FILTER] != WINED3D_TEXF_POINT)
3941  {
3942  WARN("Non-filterable texture and mip filter enabled on sampler %u, returning E_FAIL\n", i);
3943  return E_FAIL;
3944  }
3945  }
3946 
3947  if (state->render_states[WINED3D_RS_ZENABLE] || state->render_states[WINED3D_RS_ZWRITEENABLE]
3948  || state->render_states[WINED3D_RS_STENCILENABLE])
3949  {
3950  struct wined3d_rendertarget_view *rt = device->fb.render_targets[0];
3951  struct wined3d_rendertarget_view *ds = device->fb.depth_stencil;
3952 
3953  if (ds && rt && (ds->width < rt->width || ds->height < rt->height))
3954  {
3955  WARN("Depth stencil is smaller than the color buffer, returning D3DERR_CONFLICTINGRENDERSTATE\n");
3957  }
3958  }
3959 
3960  /* return a sensible default */
3961  *num_passes = 1;
3962 
3963  TRACE("returning D3D_OK\n");
3964  return WINED3D_OK;
3965 }
3966 
3968 {
3969  TRACE("device %p, software %#x.\n", device, software);
3970 
3971  device->softwareVertexProcessing = software;
3972 }
3973 
3975 {
3976  TRACE("device %p.\n", device);
3977 
3978  return device->softwareVertexProcessing;
3979 }
3980 
3982  UINT swapchain_idx, struct wined3d_raster_status *raster_status)
3983 {
3984  struct wined3d_swapchain *swapchain;
3985 
3986  TRACE("device %p, swapchain_idx %u, raster_status %p.\n",
3987  device, swapchain_idx, raster_status);
3988 
3989  if (!(swapchain = wined3d_device_get_swapchain(device, swapchain_idx)))
3990  return WINED3DERR_INVALIDCALL;
3991 
3992  return wined3d_swapchain_get_raster_status(swapchain, raster_status);
3993 }
3994 
3996 {
3997  static BOOL warned;
3998 
3999  TRACE("device %p, segments %.8e.\n", device, segments);
4000 
4001  if (segments != 0.0f)
4002  {
4003  if (!warned)
4004  {
4005  FIXME("device %p, segments %.8e stub!\n", device, segments);
4006  warned = TRUE;
4007  }
4008  }
4009 
4010  return WINED3D_OK;
4011 }
4012 
4014 {
4015  static BOOL warned;
4016 
4017  TRACE("device %p.\n", device);
4018 
4019  if (!warned)
4020  {
4021  FIXME("device %p stub!\n", device);
4022  warned = TRUE;
4023  }
4024 
4025  return 0.0f;
4026 }
4027 
4029  struct wined3d_buffer *dst_buffer, unsigned int offset, struct wined3d_unordered_access_view *uav)
4030 {
4031  TRACE("device %p, dst_buffer %p, offset %u, uav %p.\n",
4032  device, dst_buffer, offset, uav);
4033 
4034  if (offset + sizeof(GLuint) > dst_buffer->resource.size)
4035  {
4036  WARN("Offset %u too large.\n", offset);
4037  return;
4038  }
4039 
4040  wined3d_cs_emit_copy_uav_counter(device->cs, dst_buffer, offset, uav);
4041 }
4042 
4044  struct wined3d_resource *dst_resource, struct wined3d_resource *src_resource)
4045 {
4046  struct wined3d_texture *dst_texture, *src_texture;
4047  struct wined3d_box box;
4048  unsigned int i, j;
4049 
4050  TRACE("device %p, dst_resource %p, src_resource %p.\n", device, dst_resource, src_resource);
4051 
4052  if (src_resource == dst_resource)
4053  {
4054  WARN("Source and destination are the same resource.\n");
4055  return;
4056  }
4057 
4058  if (src_resource->type != dst_resource->type)
4059  {
4060  WARN("Resource types (%s / %s) don't match.\n",
4061  debug_d3dresourcetype(dst_resource->type),
4062  debug_d3dresourcetype(src_resource->type));
4063  return;
4064  }
4065 
4066  if (src_resource->width != dst_resource->width
4067  || src_resource->height != dst_resource->