ReactOS  0.4.12-dev-90-g2e2e63e
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;
209  width = wined3d_texture_get_level_width(texture, level);
210  height = wined3d_texture_get_level_height(texture, level);
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;
229  struct wined3d_rendertarget_view *dsv = fb->depth_stencil;
230  const struct wined3d_state *state = &device->cs->state;
231  struct wined3d_texture *depth_stencil = NULL;
232  const struct wined3d_gl_info *gl_info;
233  struct wined3d_texture *target = NULL;
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 (rtv && rtv->resource->type != WINED3D_RTYPE_BUFFER)
242  {
243  target = texture_from_resource(rtv->resource);
244  context = context_acquire(device, target, rtv->sub_resource_idx);
245  }
246  else
247  {
248  context = context_acquire(device, NULL, 0);
249  }
250 
251  if (dsv && dsv->resource->type != WINED3D_RTYPE_BUFFER)
252  depth_stencil = texture_from_resource(dsv->resource);
253 
254  if (!context->valid)
255  {
256  context_release(context);
257  WARN("Invalid context, skipping clear.\n");
258  return;
259  }
260  gl_info = context->gl_info;
261 
262  /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
263  * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
264  * for the cleared parts, and the untouched parts.
265  *
266  * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
267  * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
268  * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
269  * checking all this if the dest surface is in the drawable anyway. */
270  for (i = 0; i < rt_count; ++i)
271  {
272  struct wined3d_rendertarget_view *rtv = fb->render_targets[i];
273 
274  if (rtv && rtv->format->id != WINED3DFMT_NULL)
275  {
277 
278  if (flags & WINED3DCLEAR_TARGET && !is_full_clear(rt, rtv->sub_resource_idx,
279  draw_rect, rect_count ? clear_rect : NULL))
280  wined3d_texture_load_location(rt, rtv->sub_resource_idx, context, rtv->resource->draw_binding);
281  else
282  wined3d_texture_prepare_location(rt, rtv->sub_resource_idx, context, rtv->resource->draw_binding);
283  }
284  }
285 
286  if (target)
287  {
288  render_offscreen = context->render_offscreen;
289  wined3d_rendertarget_view_get_drawable_size(rtv, context, &drawable_width, &drawable_height);
290  }
291  else
292  {
293  unsigned int ds_level = dsv->sub_resource_idx % depth_stencil->level_count;
294 
295  render_offscreen = TRUE;
296  drawable_width = wined3d_texture_get_level_pow2_width(depth_stencil, ds_level);
297  drawable_height = wined3d_texture_get_level_pow2_height(depth_stencil, ds_level);
298  }
299 
300  if (depth_stencil)
301  {
302  DWORD ds_location = render_offscreen ? dsv->resource->draw_binding : WINED3D_LOCATION_DRAWABLE;
304 
306  && !is_full_clear(ds, dsv->sub_resource_idx, draw_rect, rect_count ? clear_rect : NULL))
307  wined3d_texture_load_location(ds, dsv->sub_resource_idx, context, ds_location);
308  else
309  wined3d_texture_prepare_location(ds, dsv->sub_resource_idx, context, ds_location);
310 
312  {
315  }
316  }
317 
318  if (!context_apply_clear_state(context, state, rt_count, fb))
319  {
320  context_release(context);
321  WARN("Failed to apply clear state, skipping clear.\n");
322  return;
323  }
324 
325  /* Only set the values up once, as they are not changing. */
326  if (flags & WINED3DCLEAR_STENCIL)
327  {
328  if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
329  {
330  gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
332  }
333  gl_info->gl_ops.gl.p_glStencilMask(~0U);
335  gl_info->gl_ops.gl.p_glClearStencil(stencil);
336  checkGLcall("glClearStencil");
337  clear_mask = clear_mask | GL_STENCIL_BUFFER_BIT;
338  }
339 
340  if (flags & WINED3DCLEAR_ZBUFFER)
341  {
342  gl_info->gl_ops.gl.p_glDepthMask(GL_TRUE);
344  gl_info->gl_ops.gl.p_glClearDepth(depth);
345  checkGLcall("glClearDepth");
346  clear_mask = clear_mask | GL_DEPTH_BUFFER_BIT;
347  }
348 
349  if (flags & WINED3DCLEAR_TARGET)
350  {
351  for (i = 0; i < rt_count; ++i)
352  {
353  struct wined3d_rendertarget_view *rtv = fb->render_targets[i];
354  struct wined3d_texture *texture;
355 
356  if (!rtv)
357  continue;
358 
359  if (rtv->resource->type == WINED3D_RTYPE_BUFFER)
360  {
361  FIXME("Not supported on buffer resources.\n");
362  continue;
363  }
364 
365  texture = texture_from_resource(rtv->resource);
366  wined3d_texture_validate_location(texture, rtv->sub_resource_idx, rtv->resource->draw_binding);
367  wined3d_texture_invalidate_location(texture, rtv->sub_resource_idx, ~rtv->resource->draw_binding);
368  }
369 
370  if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && needs_srgb_write(context, state, fb))
371  {
372  if (rt_count > 1)
373  WARN("Clearing multiple sRGB render targets with no GL_ARB_framebuffer_sRGB "
374  "support, this might cause graphical issues.\n");
375 
376  corrected_color.r = color->r < wined3d_srgb_const1[0]
377  ? color->r * wined3d_srgb_const0[3]
378  : pow(color->r, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1]
379  - wined3d_srgb_const0[2];
380  corrected_color.r = min(max(corrected_color.r, 0.0f), 1.0f);
381  corrected_color.g = color->g < wined3d_srgb_const1[0]
382  ? color->g * wined3d_srgb_const0[3]
383  : pow(color->g, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1]
384  - wined3d_srgb_const0[2];
385  corrected_color.g = min(max(corrected_color.g, 0.0f), 1.0f);
386  corrected_color.b = color->b < wined3d_srgb_const1[0]
387  ? color->b * wined3d_srgb_const0[3]
388  : pow(color->b, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1]
389  - wined3d_srgb_const0[2];
390  corrected_color.b = min(max(corrected_color.b, 0.0f), 1.0f);
391  color = &corrected_color;
392  }
393 
394  gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
395  for (i = 0; i < MAX_RENDER_TARGETS; ++i)
397  gl_info->gl_ops.gl.p_glClearColor(color->r, color->g, color->b, color->a);
398  checkGLcall("glClearColor");
399  clear_mask = clear_mask | GL_COLOR_BUFFER_BIT;
400  }
401 
402  if (!rect_count)
403  {
404  if (render_offscreen)
405  {
406  gl_info->gl_ops.gl.p_glScissor(draw_rect->left, draw_rect->top,
407  draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
408  }
409  else
410  {
411  gl_info->gl_ops.gl.p_glScissor(draw_rect->left, drawable_height - draw_rect->bottom,
412  draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
413  }
414  gl_info->gl_ops.gl.p_glClear(clear_mask);
415  }
416  else
417  {
418  RECT current_rect;
419 
420  /* Now process each rect in turn. */
421  for (i = 0; i < rect_count; ++i)
422  {
423  /* Note that GL uses lower left, width/height. */
424  IntersectRect(&current_rect, draw_rect, &clear_rect[i]);
425 
426  TRACE("clear_rect[%u] %s, current_rect %s.\n", i,
427  wine_dbgstr_rect(&clear_rect[i]),
428  wine_dbgstr_rect(&current_rect));
429 
430  /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
431  * The rectangle is not cleared, no error is returned, but further rectangles are
432  * still cleared if they are valid. */
433  if (current_rect.left > current_rect.right || current_rect.top > current_rect.bottom)
434  {
435  TRACE("Rectangle with negative dimensions, ignoring.\n");
436  continue;
437  }
438 
439  if (render_offscreen)
440  {
441  gl_info->gl_ops.gl.p_glScissor(current_rect.left, current_rect.top,
442  current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
443  }
444  else
445  {
446  gl_info->gl_ops.gl.p_glScissor(current_rect.left, drawable_height - current_rect.bottom,
447  current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
448  }
449  gl_info->gl_ops.gl.p_glClear(clear_mask);
450  }
451  }
453  checkGLcall("clear");
454 
455  if (flags & WINED3DCLEAR_TARGET && target->swapchain && target->swapchain->front_buffer == target)
456  gl_info->gl_ops.gl.p_glFlush();
457 
458  context_release(context);
459 }
460 
462 {
463  ULONG refcount = InterlockedIncrement(&device->ref);
464 
465  TRACE("%p increasing refcount to %u.\n", device, refcount);
466 
467  return refcount;
468 }
469 
471 {
472  struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry);
473 
474  ERR("Leftover sampler %p.\n", sampler);
475 }
476 
478 {
480 
481  TRACE("%p decreasing refcount to %u.\n", device, refcount);
482 
483  if (!refcount)
484  {
485  UINT i;
486 
487  wined3d_cs_destroy(device->cs);
488 
489  if (device->recording && wined3d_stateblock_decref(device->recording))
490  ERR("Something's still holding the recording stateblock.\n");
491  device->recording = NULL;
492 
493  state_cleanup(&device->state);
494 
495  for (i = 0; i < ARRAY_SIZE(device->multistate_funcs); ++i)
496  {
497  heap_free(device->multistate_funcs[i]);
498  device->multistate_funcs[i] = NULL;
499  }
500 
501  if (!list_empty(&device->resources))
502  {
503  struct wined3d_resource *resource;
504 
505  ERR("Device released with resources still bound.\n");
506 
508  {
509  ERR("Leftover resource %p with type %s (%#x).\n",
510  resource, debug_d3dresourcetype(resource->type), resource->type);
511  }
512  }
513 
514  if (device->contexts)
515  ERR("Context array not freed!\n");
516  if (device->hardwareCursor)
517  DestroyCursor(device->hardwareCursor);
518  device->hardwareCursor = 0;
519 
521 
522  wined3d_decref(device->wined3d);
523  device->wined3d = NULL;
524  heap_free(device);
525  TRACE("Freed device %p.\n", device);
526  }
527 
528  return refcount;
529 }
530 
532 {
533  TRACE("device %p.\n", device);
534 
535  return device->swapchain_count;
536 }
537 
539 {
540  TRACE("device %p, swapchain_idx %u.\n", device, swapchain_idx);
541 
542  if (swapchain_idx >= device->swapchain_count)
543  {
544  WARN("swapchain_idx %u >= swapchain_count %u.\n",
545  swapchain_idx, device->swapchain_count);
546  return NULL;
547  }
548 
549  return device->swapchains[swapchain_idx];
550 }
551 
552 static void device_load_logo(struct wined3d_device *device, const char *filename)
553 {
554  struct wined3d_color_key color_key;
555  struct wined3d_resource_desc desc;
556  HBITMAP hbm;
557  BITMAP bm;
558  HRESULT hr;
559  HDC dcb = NULL, dcs = NULL;
560 
561  if (!(hbm = LoadImageA(NULL, filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION)))
562  {
563  ERR_(winediag)("Failed to load logo %s.\n", wine_dbgstr_a(filename));
564  return;
565  }
566  GetObjectA(hbm, sizeof(BITMAP), &bm);
567 
568  if (!(dcb = CreateCompatibleDC(NULL)))
569  goto out;
570  SelectObject(dcb, hbm);
571 
575  desc.multisample_quality = 0;
578  desc.width = bm.bmWidth;
579  desc.height = bm.bmHeight;
580  desc.depth = 1;
581  desc.size = 0;
582  if (FAILED(hr = wined3d_texture_create(device, &desc, 1, 1,
585  {
586  ERR("Wine logo requested, but failed to create texture, hr %#x.\n", hr);
587  goto out;
588  }
589 
590  if (FAILED(hr = wined3d_texture_get_dc(device->logo_texture, 0, &dcs)))
591  {
593  device->logo_texture = NULL;
594  goto out;
595  }
596  BitBlt(dcs, 0, 0, bm.bmWidth, bm.bmHeight, dcb, 0, 0, SRCCOPY);
597  wined3d_texture_release_dc(device->logo_texture, 0, dcs);
598 
599  color_key.color_space_low_value = 0;
600  color_key.color_space_high_value = 0;
602 
603 out:
604  if (dcb) DeleteDC(dcb);
605  if (hbm) DeleteObject(hbm);
606 }
607 
608 /* Context activation is done by the caller. */
610 {
611  const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
612  const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
614  unsigned int i;
615  DWORD color;
616 
618  color = 0x000000ff;
619  else
620  color = 0x00000000;
621 
622  /* Under DirectX you can sample even if no texture is bound, whereas
623  * OpenGL will only allow that when a valid texture is bound.
624  * We emulate this by creating dummy textures and binding them
625  * to each texture stage when the currently set D3D texture is NULL. */
626  context_active_texture(context, gl_info, 0);
627 
628  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_1d);
629  TRACE("Dummy 1D texture given name %u.\n", textures->tex_1d);
630  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, textures->tex_1d);
631  gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA8, 1, 0,
633 
634  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d);
635  TRACE("Dummy 2D texture given name %u.\n", textures->tex_2d);
636  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, textures->tex_2d);
637  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0,
639 
640  if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
641  {
642  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_rect);
643  TRACE("Dummy rectangle texture given name %u.\n", textures->tex_rect);
644  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textures->tex_rect);
645  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, 1, 1, 0,
647  }
648 
649  if (gl_info->supported[EXT_TEXTURE3D])
650  {
651  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_3d);
652  TRACE("Dummy 3D texture given name %u.\n", textures->tex_3d);
653  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_3D, textures->tex_3d);
655  GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color));
656  }
657 
658  if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
659  {
660  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_cube);
661  TRACE("Dummy cube texture given name %u.\n", textures->tex_cube);
662  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP, textures->tex_cube);
664  {
665  gl_info->gl_ops.gl.p_glTexImage2D(i, 0, GL_RGBA8, 1, 1, 0,
667  }
668  }
669 
671  {
672  DWORD cube_array_data[6];
673 
674  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_cube_array);
675  TRACE("Dummy cube array texture given name %u.\n", textures->tex_cube_array);
676  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures->tex_cube_array);
677  for (i = 0; i < ARRAY_SIZE(cube_array_data); ++i)
678  cube_array_data[i] = color;
680  GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, cube_array_data));
681  }
682 
683  if (gl_info->supported[EXT_TEXTURE_ARRAY])
684  {
685  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_1d_array);
686  TRACE("Dummy 1D array texture given name %u.\n", textures->tex_1d_array);
687  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D_ARRAY, textures->tex_1d_array);
688  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, GL_RGBA8, 1, 1, 0,
690 
691  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_array);
692  TRACE("Dummy 2D array texture given name %u.\n", textures->tex_2d_array);
693  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_ARRAY, textures->tex_2d_array);
695  GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color));
696  }
697 
698  if (gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT])
699  {
700  GLuint buffer;
701 
702  GL_EXTCALL(glGenBuffers(1, &buffer));
703  GL_EXTCALL(glBindBuffer(GL_TEXTURE_BUFFER, buffer));
704  GL_EXTCALL(glBufferData(GL_TEXTURE_BUFFER, sizeof(color), &color, GL_STATIC_DRAW));
705  GL_EXTCALL(glBindBuffer(GL_TEXTURE_BUFFER, 0));
706 
707  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_buffer);
708  TRACE("Dummy buffer texture given name %u.\n", textures->tex_buffer);
709  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_BUFFER, textures->tex_buffer);
710  GL_EXTCALL(glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA8, buffer));
711  GL_EXTCALL(glDeleteBuffers(1, &buffer));
712  }
713 
714  if (gl_info->supported[ARB_TEXTURE_MULTISAMPLE])
715  {
716  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_ms);
717  TRACE("Dummy multisample texture given name %u.\n", textures->tex_2d_ms);
718  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures->tex_2d_ms);
719  GL_EXTCALL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_TRUE));
720 
721  gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_ms_array);
722  TRACE("Dummy multisample array texture given name %u.\n", textures->tex_2d_ms_array);
723  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures->tex_2d_ms_array);
724  GL_EXTCALL(glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 1, GL_RGBA8, 1, 1, 1, GL_TRUE));
725 
726  if (gl_info->supported[ARB_CLEAR_TEXTURE])
727  {
728  GL_EXTCALL(glClearTexImage(textures->tex_2d_ms, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color));
729  GL_EXTCALL(glClearTexImage(textures->tex_2d_ms_array, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color));
730  }
731  else
732  {
733  WARN("ARB_clear_texture is currently required to clear dummy multisample textures.\n");
734  }
735  }
736 
737  checkGLcall("create dummy textures");
738 
739  context_bind_dummy_textures(device, context);
740 }
741 
742 /* Context activation is done by the caller. */
744 {
745  struct wined3d_dummy_textures *dummy_textures = &device->dummy_textures;
746  const struct wined3d_gl_info *gl_info = context->gl_info;
747 
748  if (gl_info->supported[ARB_TEXTURE_MULTISAMPLE])
749  {
750  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_ms);
751  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_ms_array);
752  }
753 
754  if (gl_info->supported[ARB_TEXTURE_BUFFER_OBJECT])
755  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_buffer);
756 
757  if (gl_info->supported[EXT_TEXTURE_ARRAY])
758  {
759  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_array);
760  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_1d_array);
761  }
762 
764  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_cube_array);
765 
766  if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
767  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_cube);
768 
769  if (gl_info->supported[EXT_TEXTURE3D])
770  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_3d);
771 
772  if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
773  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_rect);
774 
775  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d);
776  gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_1d);
777 
778  checkGLcall("delete dummy textures");
779 
780  memset(dummy_textures, 0, sizeof(*dummy_textures));
781 }
782 
783 /* Context activation is done by the caller. */
785 {
786  struct wined3d_sampler_desc desc;
787  HRESULT hr;
788 
792  memset(desc.border_color, 0, sizeof(desc.border_color));
796  desc.lod_bias = 0.0f;
797  desc.min_lod = -1000.0f;
798  desc.max_lod = 1000.0f;
799  desc.mip_base_level = 0;
800  desc.max_anisotropy = 1;
801  desc.compare = FALSE;
803  desc.srgb_decode = TRUE;
804 
805  /* In SM4+ shaders there is a separation between resources and samplers. Some shader
806  * instructions allow access to resources without using samplers.
807  * In GLSL, resources are always accessed through sampler or image variables. The default
808  * sampler object is used to emulate the direct resource access when there is no sampler state
809  * to use.
810  */
811  if (FAILED(hr = wined3d_sampler_create(device, &desc, NULL, &wined3d_null_parent_ops, &device->default_sampler)))
812  {
813  ERR("Failed to create default sampler, hr %#x.\n", hr);
814  device->default_sampler = NULL;
815  }
816 
817  /* In D3D10+, a NULL sampler maps to the default sampler state. */
824  if (FAILED(hr = wined3d_sampler_create(device, &desc, NULL, &wined3d_null_parent_ops, &device->null_sampler)))
825  {
826  ERR("Failed to create null sampler, hr %#x.\n", hr);
827  device->null_sampler = NULL;
828  }
829 }
830 
831 /* Context activation is done by the caller. */
833 {
835  device->default_sampler = NULL;
837  device->null_sampler = NULL;
838 }
839 
841 {
842  /* Make sure the window is managed, otherwise we won't get keyboard input. */
843  style |= WS_POPUP | WS_SYSMENU;
844  style &= ~(WS_CAPTION | WS_THICKFRAME);
845 
846  return style;
847 }
848 
849 static LONG fullscreen_exstyle(LONG exstyle)
850 {
851  /* Filter out window decorations. */
852  exstyle &= ~(WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE);
853 
854  return exstyle;
855 }
856 
858 {
859  BOOL filter_messages;
860  LONG style, exstyle;
861 
862  TRACE("Setting up window %p for fullscreen mode.\n", window);
863 
864  if (device->style || device->exStyle)
865  {
866  ERR("Changing the window style for window %p, but another style (%08x, %08x) is already stored.\n",
867  window, device->style, device->exStyle);
868  }
869 
870  device->style = GetWindowLongW(window, GWL_STYLE);
871  device->exStyle = GetWindowLongW(window, GWL_EXSTYLE);
872 
873  style = fullscreen_style(device->style);
874  exstyle = fullscreen_exstyle(device->exStyle);
875 
876  TRACE("Old style was %08x, %08x, setting to %08x, %08x.\n",
877  device->style, device->exStyle, style, exstyle);
878 
879  filter_messages = device->filter_messages;
880  device->filter_messages = TRUE;
881 
882  SetWindowLongW(window, GWL_STYLE, style);
883  SetWindowLongW(window, GWL_EXSTYLE, exstyle);
885 
886  device->filter_messages = filter_messages;
887 }
888 
890  const RECT *window_rect)
891 {
892  unsigned int window_pos_flags = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE;
893  BOOL filter_messages;
894  LONG style, exstyle;
895  RECT rect = {0};
896 
897  if (!device->style && !device->exStyle)
898  return;
899 
900  style = GetWindowLongW(window, GWL_STYLE);
901  exstyle = GetWindowLongW(window, GWL_EXSTYLE);
902 
903  /* These flags are set by wined3d_device_setup_fullscreen_window, not the
904  * application, and we want to ignore them in the test below, since it's
905  * not the application's fault that they changed. Additionally, we want to
906  * preserve the current status of these flags (i.e. don't restore them) to
907  * more closely emulate the behavior of Direct3D, which leaves these flags
908  * alone when returning to windowed mode. */
909  device->style ^= (device->style ^ style) & WS_VISIBLE;
910  device->exStyle ^= (device->exStyle ^ exstyle) & WS_EX_TOPMOST;
911 
912  TRACE("Restoring window style of window %p to %08x, %08x.\n",
913  window, device->style, device->exStyle);
914 
915  filter_messages = device->filter_messages;
916  device->filter_messages = TRUE;
917 
918  /* Only restore the style if the application didn't modify it during the
919  * fullscreen phase. Some applications change it before calling Reset()
920  * when switching between windowed and fullscreen modes (HL2), some
921  * depend on the original style (Eve Online). */
922  if (style == fullscreen_style(device->style) && exstyle == fullscreen_exstyle(device->exStyle))
923  {
924  SetWindowLongW(window, GWL_STYLE, device->style);
925  SetWindowLongW(window, GWL_EXSTYLE, device->exStyle);
926  }
927 
928  if (window_rect)
929  rect = *window_rect;
930  else
931  window_pos_flags |= (SWP_NOMOVE | SWP_NOSIZE);
932  SetWindowPos(window, 0, rect.left, rect.top,
933  rect.right - rect.left, rect.bottom - rect.top, window_pos_flags);
934 
935  device->filter_messages = filter_messages;
936 
937  /* Delete the old values. */
938  device->style = 0;
939  device->exStyle = 0;
940 }
941 
943 {
944  TRACE("device %p, window %p.\n", device, window);
945 
946  if (!wined3d_register_window(window, device))
947  {
948  ERR("Failed to register window %p.\n", window);
949  return E_FAIL;
950  }
951 
952  InterlockedExchangePointer((void **)&device->focus_window, window);
953  SetWindowPos(window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
954 
955  return WINED3D_OK;
956 }
957 
959 {
960  TRACE("device %p.\n", device);
961 
963  InterlockedExchangePointer((void **)&device->focus_window, NULL);
964 }
965 
967 {
968  BOOL ds_enable = swapchain->desc.enable_auto_depth_stencil;
969  unsigned int i;
970 
971  for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
972  {
974  }
975  if (device->back_buffer_view)
977 
979 }
980 
982 {
983  struct wined3d_resource *resource, *cursor;
984  struct wined3d_device *device = object;
985  struct wined3d_context *context;
986  struct wined3d_shader *shader;
987 
988  LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry)
989  {
990  TRACE("Unloading resource %p.\n", resource);
991  wined3d_cs_emit_unload_resource(device->cs, resource);
992  }
993 
995  {
996  device->shader_backend->shader_destroy(shader);
997  }
998 
999  context = context_acquire(device, NULL, 0);
1000  device->blitter->ops->blitter_destroy(device->blitter, context);
1001  device->shader_backend->shader_free_private(device);
1002  destroy_dummy_textures(device, context);
1003  destroy_default_samplers(device, context);
1004  context_release(context);
1005 
1006  while (device->context_count)
1007  {
1008  if (device->contexts[0]->swapchain)
1009  swapchain_destroy_contexts(device->contexts[0]->swapchain);
1010  else
1011  context_destroy(device, device->contexts[0]);
1012  }
1013 }
1014 
1016 {
1018  device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
1019 }
1020 
1022 {
1023  struct wined3d_device *device = object;
1024  struct wined3d_swapchain *swapchain;
1025  struct wined3d_context *context;
1026  struct wined3d_texture *target;
1027  HRESULT hr;
1028 
1029  if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
1030  device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
1031  {
1032  ERR("Failed to allocate shader private data, hr %#x.\n", hr);
1033  return;
1034  }
1035 
1036  if (!(device->blitter = wined3d_cpu_blitter_create()))
1037  {
1038  ERR("Failed to create CPU blitter.\n");
1039  device->shader_backend->shader_free_private(device);
1040  return;
1041  }
1042  wined3d_ffp_blitter_create(&device->blitter, &device->adapter->gl_info);
1043  if (!wined3d_glsl_blitter_create(&device->blitter, device))
1044  wined3d_arbfp_blitter_create(&device->blitter, device);
1045  wined3d_fbo_blitter_create(&device->blitter, &device->adapter->gl_info);
1046  wined3d_raw_blitter_create(&device->blitter, &device->adapter->gl_info);
1047 
1048  swapchain = device->swapchains[0];
1049  target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer;
1050  context = context_acquire(device, target, 0);
1051  create_dummy_textures(device, context);
1052  create_default_samplers(device, context);
1053  context_release(context);
1054 }
1055 
1057 {
1059  device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
1060  if (!device->swapchains[0]->num_contexts)
1061  return E_FAIL;
1062 
1063  return WINED3D_OK;
1064 }
1065 
1067  struct wined3d_swapchain_desc *swapchain_desc)
1068 {
1069  static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 0.0f};
1070  struct wined3d_swapchain *swapchain = NULL;
1071  DWORD clear_flags = 0;
1072  HRESULT hr;
1073 
1074  TRACE("device %p, swapchain_desc %p.\n", device, swapchain_desc);
1075 
1076  if (device->d3d_initialized)
1077  return WINED3DERR_INVALIDCALL;
1078  if (device->wined3d->flags & WINED3D_NO3D)
1079  return WINED3DERR_INVALIDCALL;
1080 
1081  memset(device->fb.render_targets, 0, sizeof(device->fb.render_targets));
1082 
1083  /* Setup the implicit swapchain. This also initializes a context. */
1084  TRACE("Creating implicit swapchain.\n");
1085  if (FAILED(hr = device->device_parent->ops->create_swapchain(device->device_parent,
1086  swapchain_desc, &swapchain)))
1087  {
1088  WARN("Failed to create implicit swapchain.\n");
1089  goto err_out;
1090  }
1091 
1092  if (swapchain_desc->backbuffer_count && swapchain_desc->backbuffer_usage & WINED3DUSAGE_RENDERTARGET)
1093  {
1094  struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource;
1095  struct wined3d_view_desc view_desc;
1096 
1097  view_desc.format_id = back_buffer->format->id;
1098  view_desc.flags = 0;
1099  view_desc.u.texture.level_idx = 0;
1100  view_desc.u.texture.level_count = 1;
1101  view_desc.u.texture.layer_idx = 0;
1102  view_desc.u.texture.layer_count = 1;
1103  if (FAILED(hr = wined3d_rendertarget_view_create(&view_desc, back_buffer,
1105  {
1106  ERR("Failed to create rendertarget view, hr %#x.\n", hr);
1107  goto err_out;
1108  }
1109  }
1110 
1111  device->swapchain_count = 1;
1112  if (!(device->swapchains = heap_calloc(device->swapchain_count, sizeof(*device->swapchains))))
1113  {
1114  ERR("Out of memory!\n");
1115  goto err_out;
1116  }
1117  device->swapchains[0] = swapchain;
1118 
1120  goto err_out;
1121  device_init_swapchain_state(device, swapchain);
1122 
1123  device->contexts[0]->last_was_rhw = 0;
1124 
1125  TRACE("All defaults now set up.\n");
1126 
1127  /* Clear the screen */
1128  if (device->back_buffer_view)
1129  clear_flags |= WINED3DCLEAR_TARGET;
1130  if (swapchain_desc->enable_auto_depth_stencil)
1131  clear_flags |= WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL;
1132  if (clear_flags)
1133  wined3d_device_clear(device, 0, NULL, clear_flags, &black, 1.0f, 0);
1134 
1135  device->d3d_initialized = TRUE;
1136 
1137  if (wined3d_settings.logo)
1139  return WINED3D_OK;
1140 
1141 err_out:
1142  heap_free(device->swapchains);
1143  device->swapchain_count = 0;
1144  if (device->back_buffer_view)
1146  if (swapchain)
1147  wined3d_swapchain_decref(swapchain);
1148 
1149  return hr;
1150 }
1151 
1153  struct wined3d_swapchain_desc *swapchain_desc)
1154 {
1155  struct wined3d_swapchain *swapchain = NULL;
1156  HRESULT hr;
1157 
1158  TRACE("device %p, swapchain_desc %p.\n", device, swapchain_desc);
1159 
1160  /* Setup the implicit swapchain */
1161  TRACE("Creating implicit swapchain\n");
1162  hr = device->device_parent->ops->create_swapchain(device->device_parent,
1163  swapchain_desc, &swapchain);
1164  if (FAILED(hr))
1165  {
1166  WARN("Failed to create implicit swapchain\n");
1167  goto err_out;
1168  }
1169 
1170  device->swapchain_count = 1;
1171  if (!(device->swapchains = heap_calloc(device->swapchain_count, sizeof(*device->swapchains))))
1172  {
1173  ERR("Out of memory!\n");
1174  goto err_out;
1175  }
1176  device->swapchains[0] = swapchain;
1177 
1178  if (!(device->blitter = wined3d_cpu_blitter_create()))
1179  {
1180  ERR("Failed to create CPU blitter.\n");
1181  heap_free(device->swapchains);
1182  device->swapchain_count = 0;
1183  goto err_out;
1184  }
1185 
1186  return WINED3D_OK;
1187 
1188 err_out:
1189  wined3d_swapchain_decref(swapchain);
1190  return hr;
1191 }
1192 
1193 static void device_free_sampler(struct wine_rb_entry *entry, void *context)
1194 {
1195  struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry);
1196 
1197  wined3d_sampler_decref(sampler);
1198 }
1199 
1201 {
1202  unsigned int i;
1203 
1204  TRACE("device %p.\n", device);
1205 
1206  if (!device->d3d_initialized)
1207  return WINED3DERR_INVALIDCALL;
1208 
1209  device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
1210 
1211  if (device->logo_texture)
1213  if (device->cursor_texture)
1215 
1216  state_unbind_resources(&device->state);
1217 
1219 
1222 
1223  if (device->fb.depth_stencil)
1224  {
1225  struct wined3d_rendertarget_view *view = device->fb.depth_stencil;
1226 
1227  TRACE("Releasing depth/stencil view %p.\n", view);
1228 
1229  device->fb.depth_stencil = NULL;
1231  }
1232 
1233  if (device->auto_depth_stencil_view)
1234  {
1236 
1237  device->auto_depth_stencil_view = NULL;
1239  ERR("Something's still holding the auto depth/stencil view (%p).\n", view);
1240  }
1241 
1242  for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
1243  {
1245  }
1246  if (device->back_buffer_view)
1247  {
1249  device->back_buffer_view = NULL;
1250  }
1251 
1252  for (i = 0; i < device->swapchain_count; ++i)
1253  {
1254  TRACE("Releasing the implicit swapchain %u.\n", i);
1255  if (wined3d_swapchain_decref(device->swapchains[i]))
1256  FIXME("Something's still holding the implicit swapchain.\n");
1257  }
1258 
1259  heap_free(device->swapchains);
1260  device->swapchains = NULL;
1261  device->swapchain_count = 0;
1262 
1263  device->d3d_initialized = FALSE;
1264 
1265  return WINED3D_OK;
1266 }
1267 
1269 {
1270  unsigned int i;
1271 
1272  device->blitter->ops->blitter_destroy(device->blitter, NULL);
1273 
1274  for (i = 0; i < device->swapchain_count; ++i)
1275  {
1276  TRACE("Releasing the implicit swapchain %u.\n", i);
1277  if (wined3d_swapchain_decref(device->swapchains[i]))
1278  FIXME("Something's still holding the implicit swapchain.\n");
1279  }
1280 
1281  heap_free(device->swapchains);
1282  device->swapchains = NULL;
1283  device->swapchain_count = 0;
1284  return WINED3D_OK;
1285 }
1286 
1287 /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
1288  * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
1289  * CreateDevice if D3DCREATE_MULTITHREADED is passed.
1290  *
1291  * There is no way to deactivate thread safety once it is enabled.
1292  */
1294 {
1295  TRACE("device %p.\n", device);
1296 
1297  /* For now just store the flag (needed in case of ddraw). */
1298  device->create_parms.flags |= WINED3DCREATE_MULTITHREADED;
1299 }
1300 
1302 {
1303  /* const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; */
1304 
1305  TRACE("device %p.\n", device);
1306 
1307  /* We can not acquire the context unless there is a swapchain. */
1308  /*
1309  if (device->swapchains && gl_info->supported[NVX_GPU_MEMORY_INFO] &&
1310  !wined3d_settings.emulated_textureram)
1311  {
1312  GLint vram_free_kb;
1313  UINT64 vram_free;
1314 
1315  struct wined3d_context *context = context_acquire(device, NULL, 0);
1316  gl_info->gl_ops.gl.p_glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &vram_free_kb);
1317  vram_free = (UINT64)vram_free_kb * 1024;
1318  context_release(context);
1319 
1320  TRACE("Total 0x%s bytes. emulation 0x%s left, driver 0x%s left.\n",
1321  wine_dbgstr_longlong(device->adapter->vram_bytes),
1322  wine_dbgstr_longlong(device->adapter->vram_bytes - device->adapter->vram_bytes_used),
1323  wine_dbgstr_longlong(vram_free));
1324 
1325  vram_free = min(vram_free, device->adapter->vram_bytes - device->adapter->vram_bytes_used);
1326  return min(UINT_MAX, vram_free);
1327  }
1328  */
1329 
1330  TRACE("Emulating 0x%s bytes. 0x%s used, returning 0x%s left.\n",
1331  wine_dbgstr_longlong(device->adapter->vram_bytes),
1332  wine_dbgstr_longlong(device->adapter->vram_bytes_used),
1333  wine_dbgstr_longlong(device->adapter->vram_bytes - device->adapter->vram_bytes_used));
1334 
1335  return min(UINT_MAX, device->adapter->vram_bytes - device->adapter->vram_bytes_used);
1336 }
1337 
1339  struct wined3d_buffer *buffer, UINT offset)
1340 {
1341  struct wined3d_stream_output *stream;
1342  struct wined3d_buffer *prev_buffer;
1343 
1344  TRACE("device %p, idx %u, buffer %p, offset %u.\n", device, idx, buffer, offset);
1345 
1347  {
1348  WARN("Invalid stream output %u.\n", idx);
1349  return;
1350  }
1351 
1352  stream = &device->update_state->stream_output[idx];
1353  prev_buffer = stream->buffer;
1354 
1355  if (buffer)
1356  wined3d_buffer_incref(buffer);
1357  stream->buffer = buffer;
1358  stream->offset = offset;
1359  if (!device->recording)
1360  wined3d_cs_emit_set_stream_output(device->cs, idx, buffer, offset);
1361  if (prev_buffer)
1362  wined3d_buffer_decref(prev_buffer);
1363 }
1364 
1366  UINT idx, UINT *offset)
1367 {
1368  TRACE("device %p, idx %u, offset %p.\n", device, idx, offset);
1369 
1371  {
1372  WARN("Invalid stream output %u.\n", idx);
1373  return NULL;
1374  }
1375 
1376  if (offset)
1377  *offset = device->state.stream_output[idx].offset;
1378  return device->state.stream_output[idx].buffer;
1379 }
1380 
1383 {
1384  struct wined3d_stream_state *stream;
1385  struct wined3d_buffer *prev_buffer;
1386 
1387  TRACE("device %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
1388  device, stream_idx, buffer, offset, stride);
1389 
1390  if (stream_idx >= MAX_STREAMS)
1391  {
1392  WARN("Stream index %u out of range.\n", stream_idx);
1393  return WINED3DERR_INVALIDCALL;
1394  }
1395  else if (offset & 0x3)
1396  {
1397  WARN("Offset %u is not 4 byte aligned.\n", offset);
1398  return WINED3DERR_INVALIDCALL;
1399  }
1400 
1401  stream = &device->update_state->streams[stream_idx];
1402  prev_buffer = stream->buffer;
1403 
1404  if (device->recording)
1405  device->recording->changed.streamSource |= 1u << stream_idx;
1406 
1407  if (prev_buffer == buffer
1408  && stream->stride == stride
1409  && stream->offset == offset)
1410  {
1411  TRACE("Application is setting the old values over, nothing to do.\n");
1412  return WINED3D_OK;
1413  }
1414 
1415  stream->buffer = buffer;
1416  if (buffer)
1417  {
1418  stream->stride = stride;
1419  stream->offset = offset;
1420  wined3d_buffer_incref(buffer);
1421  }
1422 
1423  if (!device->recording)
1424  wined3d_cs_emit_set_stream_source(device->cs, stream_idx, buffer, offset, stride);
1425  if (prev_buffer)
1426  wined3d_buffer_decref(prev_buffer);
1427 
1428  return WINED3D_OK;
1429 }
1430 
1432  UINT stream_idx, struct wined3d_buffer **buffer, UINT *offset, UINT *stride)
1433 {
1434  const struct wined3d_stream_state *stream;
1435 
1436  TRACE("device %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
1437  device, stream_idx, buffer, offset, stride);
1438 
1439  if (stream_idx >= MAX_STREAMS)
1440  {
1441  WARN("Stream index %u out of range.\n", stream_idx);
1442  return WINED3DERR_INVALIDCALL;
1443  }
1444 
1445  stream = &device->state.streams[stream_idx];
1446  *buffer = stream->buffer;
1447  if (offset)
1448  *offset = stream->offset;
1449  *stride = stream->stride;
1450 
1451  return WINED3D_OK;
1452 }
1453 
1455 {
1456  struct wined3d_stream_state *stream;
1457  UINT old_flags, old_freq;
1458 
1459  TRACE("device %p, stream_idx %u, divider %#x.\n", device, stream_idx, divider);
1460 
1461  /* Verify input. At least in d3d9 this is invalid. */
1463  {
1464  WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL.\n");
1465  return WINED3DERR_INVALIDCALL;
1466  }
1467  if ((divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && !stream_idx)
1468  {
1469  WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL.\n");
1470  return WINED3DERR_INVALIDCALL;
1471  }
1472  if (!divider)
1473  {
1474  WARN("Divider is 0, returning D3DERR_INVALIDCALL.\n");
1475  return WINED3DERR_INVALIDCALL;
1476  }
1477 
1478  stream = &device->update_state->streams[stream_idx];
1479  old_flags = stream->flags;
1480  old_freq = stream->frequency;
1481 
1482  stream->flags = divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA);
1483  stream->frequency = divider & 0x7fffff;
1484 
1485  if (device->recording)
1486  device->recording->changed.streamFreq |= 1u << stream_idx;
1487  else if (stream->frequency != old_freq || stream->flags != old_flags)
1488  wined3d_cs_emit_set_stream_source_freq(device->cs, stream_idx, stream->frequency, stream->flags);
1489 
1490  return WINED3D_OK;
1491 }
1492 
1494  UINT stream_idx, UINT *divider)
1495 {
1496  const struct wined3d_stream_state *stream;
1497 
1498  TRACE("device %p, stream_idx %u, divider %p.\n", device, stream_idx, divider);
1499 
1500  stream = &device->state.streams[stream_idx];
1501  *divider = stream->flags | stream->frequency;
1502 
1503  TRACE("Returning %#x.\n", *divider);
1504 
1505  return WINED3D_OK;
1506 }
1507 
1509  enum wined3d_transform_state d3dts, const struct wined3d_matrix *matrix)
1510 {
1511  TRACE("device %p, state %s, matrix %p.\n",
1512  device, debug_d3dtstype(d3dts), matrix);
1513  TRACE("%.8e %.8e %.8e %.8e\n", matrix->_11, matrix->_12, matrix->_13, matrix->_14);
1514  TRACE("%.8e %.8e %.8e %.8e\n", matrix->_21, matrix->_22, matrix->_23, matrix->_24);
1515  TRACE("%.8e %.8e %.8e %.8e\n", matrix->_31, matrix->_32, matrix->_33, matrix->_34);
1516  TRACE("%.8e %.8e %.8e %.8e\n", matrix->_41, matrix->_42, matrix->_43, matrix->_44);
1517 
1518  /* Handle recording of state blocks. */
1519  if (device->recording)
1520  {
1521  TRACE("Recording... not performing anything.\n");
1522  device->recording->changed.transform[d3dts >> 5] |= 1u << (d3dts & 0x1f);
1523  device->update_state->transforms[d3dts] = *matrix;
1524  return;
1525  }
1526 
1527  /* If the new matrix is the same as the current one,
1528  * we cut off any further processing. this seems to be a reasonable
1529  * optimization because as was noticed, some apps (warcraft3 for example)
1530  * tend towards setting the same matrix repeatedly for some reason.
1531  *
1532  * From here on we assume that the new matrix is different, wherever it matters. */
1533  if (!memcmp(&device->state.transforms[d3dts], matrix, sizeof(*matrix)))
1534  {
1535  TRACE("The application is setting the same matrix over again.\n");
1536  return;
1537  }
1538 
1539  device->state.transforms[d3dts] = *matrix;
1540  wined3d_cs_emit_set_transform(device->cs, d3dts, matrix);
1541 }
1542 
1545 {
1546  TRACE("device %p, state %s, matrix %p.\n", device, debug_d3dtstype(state), matrix);
1547 
1548  *matrix = device->state.transforms[state];
1549 }
1550 
1552  enum wined3d_transform_state state, const struct wined3d_matrix *matrix)
1553 {
1554  const struct wined3d_matrix *mat;
1555  struct wined3d_matrix temp;
1556 
1557  TRACE("device %p, state %s, matrix %p.\n", device, debug_d3dtstype(state), matrix);
1558 
1559  /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1560  * below means it will be recorded in a state block change, but it
1561  * works regardless where it is recorded.
1562  * If this is found to be wrong, change to StateBlock. */
1563  if (state > HIGHEST_TRANSFORMSTATE)
1564  {
1565  WARN("Unhandled transform state %#x.\n", state);
1566  return;
1567  }
1568 
1569  mat = &device->update_state->transforms[state];
1570  multiply_matrix(&temp, mat, matrix);
1571 
1572  /* Apply change via set transform - will reapply to eg. lights this way. */
1573  wined3d_device_set_transform(device, state, &temp);
1574 }
1575 
1576 /* Note lights are real special cases. Although the device caps state only
1577  * e.g. 8 are supported, you can reference any indexes you want as long as
1578  * that number max are enabled at any one point in time. Therefore since the
1579  * indices can be anything, we need a hashmap of them. However, this causes
1580  * stateblock problems. When capturing the state block, I duplicate the
1581  * hashmap, but when recording, just build a chain pretty much of commands to
1582  * be replayed. */
1584  UINT light_idx, const struct wined3d_light *light)
1585 {
1586  UINT hash_idx = LIGHTMAP_HASHFUNC(light_idx);
1587  struct wined3d_light_info *object = NULL;
1588  float rho;
1589 
1590  TRACE("device %p, light_idx %u, light %p.\n", device, light_idx, light);
1591 
1592  /* Check the parameter range. Need for speed most wanted sets junk lights
1593  * which confuse the GL driver. */
1594  if (!light)
1595  return WINED3DERR_INVALIDCALL;
1596 
1597  switch (light->type)
1598  {
1599  case WINED3D_LIGHT_POINT:
1600  case WINED3D_LIGHT_SPOT:
1601  case WINED3D_LIGHT_GLSPOT:
1602  /* Incorrect attenuation values can cause the gl driver to crash.
1603  * Happens with Need for speed most wanted. */
1604  if (light->attenuation0 < 0.0f || light->attenuation1 < 0.0f || light->attenuation2 < 0.0f)
1605  {
1606  WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL.\n");
1607  return WINED3DERR_INVALIDCALL;
1608  }
1609  break;
1610 
1613  /* Ignores attenuation */
1614  break;
1615 
1616  default:
1617  WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
1618  return WINED3DERR_INVALIDCALL;
1619  }
1620 
1621  if (!(object = wined3d_state_get_light(device->update_state, light_idx)))
1622  {
1623  TRACE("Adding new light\n");
1624  if (!(object = heap_alloc_zero(sizeof(*object))))
1625  return E_OUTOFMEMORY;
1626 
1627  list_add_head(&device->update_state->light_map[hash_idx], &object->entry);
1628  object->glIndex = -1;
1629  object->OriginalIndex = light_idx;
1630  }
1631 
1632  /* Initialize the object. */
1633  TRACE("Light %u setting to type %#x, diffuse %s, specular %s, ambient %s, "
1634  "position {%.8e, %.8e, %.8e}, direction {%.8e, %.8e, %.8e}, "
1635  "range %.8e, falloff %.8e, theta %.8e, phi %.8e.\n",
1636  light_idx, light->type, debug_color(&light->diffuse),
1637  debug_color(&light->specular), debug_color(&light->ambient),
1638  light->position.x, light->position.y, light->position.z,
1639  light->direction.x, light->direction.y, light->direction.z,
1640  light->range, light->falloff, light->theta, light->phi);
1641 
1642  /* Save away the information. */
1643  object->OriginalParms = *light;
1644 
1645  switch (light->type)
1646  {
1647  case WINED3D_LIGHT_POINT:
1648  /* Position */
1649  object->position.x = light->position.x;
1650  object->position.y = light->position.y;
1651  object->position.z = light->position.z;
1652  object->position.w = 1.0f;
1653  object->cutoff = 180.0f;
1654  /* FIXME: Range */
1655  break;
1656 
1658  /* Direction */
1659  object->direction.x = -light->direction.x;
1660  object->direction.y = -light->direction.y;
1661  object->direction.z = -light->direction.z;
1662  object->direction.w = 0.0f;
1663  object->exponent = 0.0f;
1664  object->cutoff = 180.0f;
1665  break;
1666 
1667  case WINED3D_LIGHT_SPOT:
1668  /* Position */
1669  object->position.x = light->position.x;
1670  object->position.y = light->position.y;
1671  object->position.z = light->position.z;
1672  object->position.w = 1.0f;
1673 
1674  /* Direction */
1675  object->direction.x = light->direction.x;
1676  object->direction.y = light->direction.y;
1677  object->direction.z = light->direction.z;
1678  object->direction.w = 0.0f;
1679 
1680  /* opengl-ish and d3d-ish spot lights use too different models
1681  * for the light "intensity" as a function of the angle towards
1682  * the main light direction, so we only can approximate very
1683  * roughly. However, spot lights are rather rarely used in games
1684  * (if ever used at all). Furthermore if still used, probably
1685  * nobody pays attention to such details. */
1686  if (!light->falloff)
1687  {
1688  /* Falloff = 0 is easy, because d3d's and opengl's spot light
1689  * equations have the falloff resp. exponent parameter as an
1690  * exponent, so the spot light lighting will always be 1.0 for
1691  * both of them, and we don't have to care for the rest of the
1692  * rather complex calculation. */
1693  object->exponent = 0.0f;
1694  }
1695  else
1696  {
1697  rho = light->theta + (light->phi - light->theta) / (2 * light->falloff);
1698  if (rho < 0.0001f)
1699  rho = 0.0001f;
1700  object->exponent = -0.3f / logf(cosf(rho / 2));
1701  }
1702 
1703  if (object->exponent > 128.0f)
1704  object->exponent = 128.0f;
1705 
1706  object->cutoff = (float)(light->phi * 90 / M_PI);
1707  /* FIXME: Range */
1708  break;
1709 
1711  object->position.x = light->position.x;
1712  object->position.y = light->position.y;
1713  object->position.z = light->position.z;
1714  object->position.w = 1.0f;
1715  break;
1716 
1717  default:
1718  FIXME("Unrecognized light type %#x.\n", light->type);
1719  }
1720 
1721  if (!device->recording)
1722  wined3d_cs_emit_set_light(device->cs, object);
1723 
1724  return WINED3D_OK;
1725 }
1726 
1728  UINT light_idx, struct wined3d_light *light)
1729 {
1730  struct wined3d_light_info *light_info;
1731 
1732  TRACE("device %p, light_idx %u, light %p.\n", device, light_idx, light);
1733 
1734  if (!(light_info = wined3d_state_get_light(&device->state, light_idx)))
1735  {
1736  TRACE("Light information requested but light not defined\n");
1737  return WINED3DERR_INVALIDCALL;
1738  }
1739 
1740  *light = light_info->OriginalParms;
1741  return WINED3D_OK;
1742 }
1743 
1745 {
1746  struct wined3d_light_info *light_info;
1747 
1748  TRACE("device %p, light_idx %u, enable %#x.\n", device, light_idx, enable);
1749 
1750  /* Special case - enabling an undefined light creates one with a strict set of parameters. */
1751  if (!(light_info = wined3d_state_get_light(device->update_state, light_idx)))
1752  {
1753  TRACE("Light enabled requested but light not defined, so defining one!\n");
1754  wined3d_device_set_light(device, light_idx, &WINED3D_default_light);
1755 
1756  if (!(light_info = wined3d_state_get_light(device->update_state, light_idx)))
1757  {
1758  FIXME("Adding default lights has failed dismally\n");
1759  return WINED3DERR_INVALIDCALL;
1760  }
1761  }
1762 
1763  wined3d_state_enable_light(device->update_state, &device->adapter->d3d_info, light_info, enable);
1764  if (!device->recording)
1765  wined3d_cs_emit_set_light_enable(device->cs, light_idx, enable);
1766 
1767  return WINED3D_OK;
1768 }
1769 
1771 {
1772  struct wined3d_light_info *light_info;
1773 
1774  TRACE("device %p, light_idx %u, enable %p.\n", device, light_idx, enable);
1775 
1776  if (!(light_info = wined3d_state_get_light(&device->state, light_idx)))
1777  {
1778  TRACE("Light enabled state requested but light not defined.\n");
1779  return WINED3DERR_INVALIDCALL;
1780  }
1781  /* true is 128 according to SetLightEnable */
1782  *enable = light_info->enabled ? 128 : 0;
1783  return WINED3D_OK;
1784 }
1785 
1787  UINT plane_idx, const struct wined3d_vec4 *plane)
1788 {
1789  TRACE("device %p, plane_idx %u, plane %p.\n", device, plane_idx, plane);
1790 
1791  if (plane_idx >= device->adapter->gl_info.limits.user_clip_distances)
1792  {
1793  TRACE("Application has requested clipplane this device doesn't support.\n");
1794  return WINED3DERR_INVALIDCALL;
1795  }
1796 
1797  if (device->recording)
1798  device->recording->changed.clipplane |= 1u << plane_idx;
1799 
1800  if (!memcmp(&device->update_state->clip_planes[plane_idx], plane, sizeof(*plane)))
1801  {
1802  TRACE("Application is setting old values over, nothing to do.\n");
1803  return WINED3D_OK;
1804  }
1805 
1806  device->update_state->clip_planes[plane_idx] = *plane;
1807 
1808  if (!device->recording)
1809  wined3d_cs_emit_set_clip_plane(device->cs, plane_idx, plane);
1810 
1811  return WINED3D_OK;
1812 }
1813 
1815  UINT plane_idx, struct wined3d_vec4 *plane)
1816 {
1817  TRACE("device %p, plane_idx %u, plane %p.\n", device, plane_idx, plane);
1818 
1819  if (plane_idx >= device->adapter->gl_info.limits.user_clip_distances)
1820  {
1821  TRACE("Application has requested clipplane this device doesn't support.\n");
1822  return WINED3DERR_INVALIDCALL;
1823  }
1824 
1825  *plane = device->state.clip_planes[plane_idx];
1826 
1827  return WINED3D_OK;
1828 }
1829 
1831  const struct wined3d_clip_status *clip_status)
1832 {
1833  FIXME("device %p, clip_status %p stub!\n", device, clip_status);
1834 
1835  if (!clip_status)
1836  return WINED3DERR_INVALIDCALL;
1837 
1838  return WINED3D_OK;
1839 }
1840 
1842  struct wined3d_clip_status *clip_status)
1843 {
1844  FIXME("device %p, clip_status %p stub!\n", device, clip_status);
1845 
1846  if (!clip_status)
1847  return WINED3DERR_INVALIDCALL;
1848 
1849  return WINED3D_OK;
1850 }
1851 
1853 {
1854  TRACE("device %p, material %p.\n", device, material);
1855 
1856  device->update_state->material = *material;
1857 
1858  if (device->recording)
1859  device->recording->changed.material = TRUE;
1860  else
1861  wined3d_cs_emit_set_material(device->cs, material);
1862 }
1863 
1865 {
1866  TRACE("device %p, material %p.\n", device, material);
1867 
1868  *material = device->state.material;
1869 
1870  TRACE("diffuse %s\n", debug_color(&material->diffuse));
1871  TRACE("ambient %s\n", debug_color(&material->ambient));
1872  TRACE("specular %s\n", debug_color(&material->specular));
1873  TRACE("emissive %s\n", debug_color(&material->emissive));
1874  TRACE("power %.8e.\n", material->power);
1875 }
1876 
1878  struct wined3d_buffer *buffer, enum wined3d_format_id format_id, unsigned int offset)
1879 {
1880  enum wined3d_format_id prev_format;
1881  struct wined3d_buffer *prev_buffer;
1882  unsigned int prev_offset;
1883 
1884  TRACE("device %p, buffer %p, format %s, offset %u.\n",
1885  device, buffer, debug_d3dformat(format_id), offset);
1886 
1887  prev_buffer = device->update_state->index_buffer;
1888  prev_format = device->update_state->index_format;
1889  prev_offset = device->update_state->index_offset;
1890 
1891  device->update_state->index_buffer = buffer;
1892  device->update_state->index_format = format_id;
1893  device->update_state->index_offset = offset;
1894 
1895  if (device->recording)
1896  device->recording->changed.indices = TRUE;
1897 
1898  if (prev_buffer == buffer && prev_format == format_id && prev_offset == offset)
1899  return;
1900 
1901  if (buffer)
1902  wined3d_buffer_incref(buffer);
1903  if (!device->recording)
1904  wined3d_cs_emit_set_index_buffer(device->cs, buffer, format_id, offset);
1905  if (prev_buffer)
1906  wined3d_buffer_decref(prev_buffer);
1907 }
1908 
1910  enum wined3d_format_id *format, unsigned int *offset)
1911 {
1912  TRACE("device %p, format %p, offset %p.\n", device, format, offset);
1913 
1914  *format = device->state.index_format;
1915  if (offset)
1916  *offset = device->state.index_offset;
1917  return device->state.index_buffer;
1918 }
1919 
1921 {
1922  TRACE("device %p, base_index %d.\n", device, base_index);
1923 
1924  device->update_state->base_vertex_index = base_index;
1925 }
1926 
1928 {
1929  TRACE("device %p.\n", device);
1930 
1931  return device->state.base_vertex_index;
1932 }
1933 
1934 void CDECL wined3d_device_set_viewports(struct wined3d_device *device, unsigned int viewport_count,
1935  const struct wined3d_viewport *viewports)
1936 {
1937  unsigned int i;
1938 
1939  TRACE("device %p, viewport_count %u, viewports %p.\n", device, viewport_count, viewports);
1940 
1941  for (i = 0; i < viewport_count; ++i)
1942  {
1943  TRACE("%u: x %.8e, y %.8e, w %.8e, h %.8e, min_z %.8e, max_z %.8e.\n", i, viewports[i].x, viewports[i].y,
1944  viewports[i].width, viewports[i].height, viewports[i].min_z, viewports[i].max_z);
1945  }
1946 
1947  if (viewport_count)
1948  memcpy(device->update_state->viewports, viewports, viewport_count * sizeof(*viewports));
1949  else
1950  memset(device->update_state->viewports, 0, sizeof(device->update_state->viewports));
1951  device->update_state->viewport_count = viewport_count;
1952 
1953  /* Handle recording of state blocks */
1954  if (device->recording)
1955  {
1956  TRACE("Recording... not performing anything\n");
1957  device->recording->changed.viewport = TRUE;
1958  return;
1959  }
1960 
1961  wined3d_cs_emit_set_viewports(device->cs, viewport_count, viewports);
1962 }
1963 
1964 void CDECL wined3d_device_get_viewports(const struct wined3d_device *device, unsigned int *viewport_count,
1965  struct wined3d_viewport *viewports)
1966 {
1967  unsigned int count;
1968 
1969  TRACE("device %p, viewport_count %p, viewports %p.\n", device, viewport_count, viewports);
1970 
1971  count = viewport_count ? min(*viewport_count, device->state.viewport_count) : 1;
1972  if (count && viewports)
1973  memcpy(viewports, device->state.viewports, count * sizeof(*viewports));
1974  if (viewport_count)
1975  *viewport_count = device->state.viewport_count;
1976 }
1977 
1979 {
1980  const struct wined3d_state *state = &device->state;
1981  struct wined3d_rendertarget_view *src_view;
1982  struct wined3d_resource *dst_resource;
1983  struct wined3d_texture *dst_texture;
1984 
1985  if (!(dst_texture = state->textures[0]))
1986  return;
1987  dst_resource = &dst_texture->resource;
1988  if (!(dst_resource->format_flags & WINED3DFMT_FLAG_DEPTH))
1989  return;
1990  if (!(src_view = state->fb->depth_stencil))
1991  return;
1992 
1993  wined3d_device_resolve_sub_resource(device, dst_resource, 0,
1994  src_view->resource, src_view->sub_resource_idx, dst_resource->format->id);
1995 }
1996 
1998 {
1999  struct wined3d_blend_state *prev;
2000 
2001  TRACE("device %p, blend_state %p.\n", device, blend_state);
2002 
2003  prev = device->update_state->blend_state;
2004  if (prev == blend_state)
2005  return;
2006 
2007  if (blend_state)
2008  wined3d_blend_state_incref(blend_state);
2009  device->update_state->blend_state = blend_state;
2010  wined3d_cs_emit_set_blend_state(device->cs, blend_state);
2011  if (prev)
2013 }
2014 
2016 {
2017  TRACE("device %p.\n", device);
2018 
2019  return device->state.blend_state;
2020 }
2021 
2023  struct wined3d_rasterizer_state *rasterizer_state)
2024 {
2025  struct wined3d_rasterizer_state *prev;
2026 
2027  TRACE("device %p, rasterizer_state %p.\n", device, rasterizer_state);
2028 
2029  prev = device->update_state->rasterizer_state;
2030  if (prev == rasterizer_state)
2031  return;
2032 
2033  if (rasterizer_state)
2034  wined3d_rasterizer_state_incref(rasterizer_state);
2035  device->update_state->rasterizer_state = rasterizer_state;
2036  wined3d_cs_emit_set_rasterizer_state(device->cs, rasterizer_state);
2037  if (prev)
2039 }
2040 
2042 {
2043  TRACE("device %p.\n", device);
2044 
2045  return device->state.rasterizer_state;
2046 }
2047 
2050 {
2051  DWORD old_value;
2052 
2053  TRACE("device %p, state %s (%#x), value %#x.\n", device, debug_d3drenderstate(state), state, value);
2054 
2055  if (state > WINEHIGHEST_RENDER_STATE)
2056  {
2057  WARN("Unhandled render state %#x.\n", state);
2058  return;
2059  }
2060 
2061  old_value = device->state.render_states[state];
2062  device->update_state->render_states[state] = value;
2063 
2064  /* Handle recording of state blocks. */
2065  if (device->recording)
2066  {
2067  TRACE("Recording... not performing anything.\n");
2068  device->recording->changed.renderState[state >> 5] |= 1u << (state & 0x1f);
2069  return;
2070  }
2071 
2072  /* Compared here and not before the assignment to allow proper stateblock recording. */
2073  if (value == old_value)
2074  TRACE("Application is setting the old value over, nothing to do.\n");
2075  else
2076  wined3d_cs_emit_set_render_state(device->cs, state, value);
2077 
2078  if (state == WINED3D_RS_POINTSIZE && value == WINED3D_RESZ_CODE)
2079  {
2080  TRACE("RESZ multisampled depth buffer resolve triggered.\n");
2081  resolve_depth_buffer(device);
2082  }
2083 }
2084 
2086 {
2087  TRACE("device %p, state %s (%#x).\n", device, debug_d3drenderstate(state), state);
2088 
2089  return device->state.render_states[state];
2090 }
2091 
2093  UINT sampler_idx, enum wined3d_sampler_state state, DWORD value)
2094 {
2095  DWORD old_value;
2096 
2097  TRACE("device %p, sampler_idx %u, state %s, value %#x.\n",
2098  device, sampler_idx, debug_d3dsamplerstate(state), value);
2099 
2100  if (sampler_idx >= WINED3DVERTEXTEXTURESAMPLER0 && sampler_idx <= WINED3DVERTEXTEXTURESAMPLER3)
2102 
2103  if (sampler_idx >= ARRAY_SIZE(device->state.sampler_states))
2104  {
2105  WARN("Invalid sampler %u.\n", sampler_idx);
2106  return; /* Windows accepts overflowing this array ... we do not. */
2107  }
2108 
2109  old_value = device->state.sampler_states[sampler_idx][state];
2110  device->update_state->sampler_states[sampler_idx][state] = value;
2111 
2112  /* Handle recording of state blocks. */
2113  if (device->recording)
2114  {
2115  TRACE("Recording... not performing anything.\n");
2116  device->recording->changed.samplerState[sampler_idx] |= 1u << state;
2117  return;
2118  }
2119 
2120  if (old_value == value)
2121  {
2122  TRACE("Application is setting the old value over, nothing to do.\n");
2123  return;
2124  }
2125 
2126  wined3d_cs_emit_set_sampler_state(device->cs, sampler_idx, state, value);
2127 }
2128 
2130  UINT sampler_idx, enum wined3d_sampler_state state)
2131 {
2132  TRACE("device %p, sampler_idx %u, state %s.\n",
2133  device, sampler_idx, debug_d3dsamplerstate(state));
2134 
2135  if (sampler_idx >= WINED3DVERTEXTEXTURESAMPLER0 && sampler_idx <= WINED3DVERTEXTEXTURESAMPLER3)
2137 
2138  if (sampler_idx >= ARRAY_SIZE(device->state.sampler_states))
2139  {
2140  WARN("Invalid sampler %u.\n", sampler_idx);
2141  return 0; /* Windows accepts overflowing this array ... we do not. */
2142  }
2143 
2144  return device->state.sampler_states[sampler_idx][state];
2145 }
2146 
2147 void CDECL wined3d_device_set_scissor_rects(struct wined3d_device *device, unsigned int rect_count,
2148  const RECT *rects)
2149 {
2150  unsigned int i;
2151 
2152  TRACE("device %p, rect_count %u, rects %p.\n", device, rect_count, rects);
2153 
2154  for (i = 0; i < rect_count; ++i)
2155  {
2156  TRACE("%u: %s\n", i, wine_dbgstr_rect(&rects[i]));
2157  }
2158 
2159  if (device->recording)
2160  device->recording->changed.scissorRect = TRUE;
2161 
2162  if (device->update_state->scissor_rect_count == rect_count
2163  && !memcmp(device->update_state->scissor_rects, rects, rect_count * sizeof(*rects)))
2164  {
2165  TRACE("App is setting the old scissor rectangles over, nothing to do.\n");
2166  return;
2167  }
2168 
2169  if (rect_count)
2170  memcpy(device->update_state->scissor_rects, rects, rect_count * sizeof(*rects));
2171  else
2172  memset(device->update_state->scissor_rects, 0, sizeof(device->update_state->scissor_rects));
2173  device->update_state->scissor_rect_count = rect_count;
2174 
2175  if (device->recording)
2176  {
2177  TRACE("Recording... not performing anything.\n");
2178  return;
2179  }
2180 
2181  wined3d_cs_emit_set_scissor_rects(device->cs, rect_count, rects);
2182 }
2183 
2184 void CDECL wined3d_device_get_scissor_rects(const struct wined3d_device *device, unsigned int *rect_count, RECT *rects)
2185 {
2186  unsigned int count;
2187 
2188  TRACE("device %p, rect_count %p, rects %p.\n", device, rect_count, rects);
2189 
2190  count = rect_count ? min(*rect_count, device->state.scissor_rect_count) : 1;
2191  if (count && rects)
2192  memcpy(rects, device->state.scissor_rects, count * sizeof(*rects));
2193  if (rect_count)
2194  *rect_count = device->state.scissor_rect_count;
2195 }
2196 
2199 {
2200  struct wined3d_vertex_declaration *prev = device->update_state->vertex_declaration;
2201 
2202  TRACE("device %p, declaration %p.\n", device, declaration);
2203 
2204  if (device->recording)
2205  device->recording->changed.vertexDecl = TRUE;
2206 
2207  if (declaration == prev)
2208  return;
2209 
2210  if (declaration)
2211  wined3d_vertex_declaration_incref(declaration);
2212  device->update_state->vertex_declaration = declaration;
2213  if (!device->recording)
2214  wined3d_cs_emit_set_vertex_declaration(device->cs, declaration);
2215  if (prev)
2217 }
2218 
2220 {
2221  TRACE("device %p.\n", device);
2222 
2223  return device->state.vertex_declaration;
2224 }
2225 
2227 {
2228  struct wined3d_shader *prev = device->update_state->shader[WINED3D_SHADER_TYPE_VERTEX];
2229 
2230  TRACE("device %p, shader %p.\n", device, shader);
2231 
2232  if (device->recording)
2233  device->recording->changed.vertexShader = TRUE;
2234 
2235  if (shader == prev)
2236  return;
2237 
2238  if (shader)
2239  wined3d_shader_incref(shader);
2240  device->update_state->shader[WINED3D_SHADER_TYPE_VERTEX] = shader;
2241  if (!device->recording)
2243  if (prev)
2244  wined3d_shader_decref(prev);
2245 }
2246 
2248 {
2249  TRACE("device %p.\n", device);
2250 
2251  return device->state.shader[WINED3D_SHADER_TYPE_VERTEX];
2252 }
2253 
2256 {
2257  struct wined3d_buffer *prev;
2258 
2259  if (idx >= MAX_CONSTANT_BUFFERS)
2260  {
2261  WARN("Invalid constant buffer index %u.\n", idx);
2262  return;
2263  }
2264 
2265  prev = device->update_state->cb[type][idx];
2266  if (buffer == prev)
2267  return;
2268 
2269  if (buffer)
2270  wined3d_buffer_incref(buffer);
2271  device->update_state->cb[type][idx] = buffer;
2272  if (!device->recording)
2273  wined3d_cs_emit_set_constant_buffer(device->cs, type, idx, buffer);
2274  if (prev)
2275  wined3d_buffer_decref(prev);
2276 }
2277 
2279 {
2280  TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2281 
2283 }
2284 
2286  enum wined3d_shader_type shader_type, unsigned int idx)
2287 {
2288  if (idx >= MAX_CONSTANT_BUFFERS)
2289  {
2290  WARN("Invalid constant buffer index %u.\n", idx);
2291  return NULL;
2292  }
2293 
2294  return device->state.cb[shader_type][idx];
2295 }
2296 
2298 {
2299  TRACE("device %p, idx %u.\n", device, idx);
2300 
2302 }
2303 
2306 {
2307  struct wined3d_shader_resource_view *prev;
2308 
2309  if (idx >= MAX_SHADER_RESOURCE_VIEWS)
2310  {
2311  WARN("Invalid view index %u.\n", idx);
2312  return;
2313  }
2314 
2315  prev = device->update_state->shader_resource_view[type][idx];
2316  if (view == prev)
2317  return;
2318 
2319  if (view)
2321  device->update_state->shader_resource_view[type][idx] = view;
2322  if (!device->recording)
2323  wined3d_cs_emit_set_shader_resource_view(device->cs, type, idx, view);
2324  if (prev)
2326 }
2327 
2330 {
2331  TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2332 
2334 }
2335 
2337  const struct wined3d_device *device, enum wined3d_shader_type shader_type, unsigned int idx)
2338 {
2339  if (idx >= MAX_SHADER_RESOURCE_VIEWS)
2340  {
2341  WARN("Invalid view index %u.\n", idx);
2342  return NULL;
2343  }
2344 
2345  return device->state.shader_resource_view[shader_type][idx];
2346 }
2347 
2349  UINT idx)
2350 {
2351  TRACE("device %p, idx %u.\n", device, idx);
2352 
2354 }
2355 
2358 {
2359  struct wined3d_sampler *prev;
2360 
2361  if (idx >= MAX_SAMPLER_OBJECTS)
2362  {
2363  WARN("Invalid sampler index %u.\n", idx);
2364  return;
2365  }
2366 
2367  prev = device->update_state->sampler[type][idx];
2368  if (sampler == prev)
2369  return;
2370 
2371  if (sampler)
2372  wined3d_sampler_incref(sampler);
2373  device->update_state->sampler[type][idx] = sampler;
2374  if (!device->recording)
2375  wined3d_cs_emit_set_sampler(device->cs, type, idx, sampler);
2376  if (prev)
2377  wined3d_sampler_decref(prev);
2378 }
2379 
2381 {
2382  TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2383 
2385 }
2386 
2388  enum wined3d_shader_type shader_type, unsigned int idx)
2389 {
2390  if (idx >= MAX_SAMPLER_OBJECTS)
2391  {
2392  WARN("Invalid sampler index %u.\n", idx);
2393  return NULL;
2394  }
2395 
2396  return device->state.sampler[shader_type][idx];
2397 }
2398 
2400 {
2401  TRACE("device %p, idx %u.\n", device, idx);
2402 
2404 }
2405 
2407  unsigned int start_idx, unsigned int count, const BOOL *constants)
2408 {
2409  unsigned int i;
2410 
2411  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2412  device, start_idx, count, constants);
2413 
2414  if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
2415  return WINED3DERR_INVALIDCALL;
2416 
2417  if (count > WINED3D_MAX_CONSTS_B - start_idx)
2418  count = WINED3D_MAX_CONSTS_B - start_idx;
2419  memcpy(&device->update_state->vs_consts_b[start_idx], constants, count * sizeof(*constants));
2420  if (TRACE_ON(d3d))
2421  {
2422  for (i = 0; i < count; ++i)
2423  TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]);
2424  }
2425 
2426  if (device->recording)
2427  {
2428  for (i = start_idx; i < count + start_idx; ++i)
2429  device->recording->changed.vertexShaderConstantsB |= (1u << i);
2430  }
2431  else
2432  {
2433  wined3d_cs_push_constants(device->cs, WINED3D_PUSH_CONSTANTS_VS_B, start_idx, count, constants);
2434  }
2435 
2436  return WINED3D_OK;
2437 }
2438 
2440  unsigned int start_idx, unsigned int count, BOOL *constants)
2441 {
2442  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2443  device, start_idx, count, constants);
2444 
2445  if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
2446  return WINED3DERR_INVALIDCALL;
2447 
2448  if (count > WINED3D_MAX_CONSTS_B - start_idx)
2449  count = WINED3D_MAX_CONSTS_B - start_idx;
2450  memcpy(constants, &device->state.vs_consts_b[start_idx], count * sizeof(*constants));
2451 
2452  return WINED3D_OK;
2453 }
2454 
2456  unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants)
2457 {
2458  unsigned int i;
2459 
2460  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2461  device, start_idx, count, constants);
2462 
2463  if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
2464  return WINED3DERR_INVALIDCALL;
2465 
2466  if (count > WINED3D_MAX_CONSTS_I - start_idx)
2467  count = WINED3D_MAX_CONSTS_I - start_idx;
2468  memcpy(&device->update_state->vs_consts_i[start_idx], constants, count * sizeof(*constants));
2469  if (TRACE_ON(d3d))
2470  {
2471  for (i = 0; i < count; ++i)
2472  TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i]));
2473  }
2474 
2475  if (device->recording)
2476  {
2477  for (i = start_idx; i < count + start_idx; ++i)
2478  device->recording->changed.vertexShaderConstantsI |= (1u << i);
2479  }
2480  else
2481  {
2482  wined3d_cs_push_constants(device->cs, WINED3D_PUSH_CONSTANTS_VS_I, start_idx, count, constants);
2483  }
2484 
2485  return WINED3D_OK;
2486 }
2487 
2489  unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants)
2490 {
2491  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2492  device, start_idx, count, constants);
2493 
2494  if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
2495  return WINED3DERR_INVALIDCALL;
2496 
2497  if (count > WINED3D_MAX_CONSTS_I - start_idx)
2498  count = WINED3D_MAX_CONSTS_I - start_idx;
2499  memcpy(constants, &device->state.vs_consts_i[start_idx], count * sizeof(*constants));
2500  return WINED3D_OK;
2501 }
2502 
2504  unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants)
2505 {
2506  const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
2507  unsigned int i;
2508 
2509  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2510  device, start_idx, count, constants);
2511 
2512  if (!constants || start_idx >= d3d_info->limits.vs_uniform_count
2513  || count > d3d_info->limits.vs_uniform_count - start_idx)
2514  return WINED3DERR_INVALIDCALL;
2515 
2516  memcpy(&device->update_state->vs_consts_f[start_idx], constants, count * sizeof(*constants));
2517  if (TRACE_ON(d3d))
2518  {
2519  for (i = 0; i < count; ++i)
2520  TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i]));
2521  }
2522 
2523  if (device->recording)
2524  memset(&device->recording->changed.vs_consts_f[start_idx], 1,
2525  count * sizeof(*device->recording->changed.vs_consts_f));
2526  else
2527  wined3d_cs_push_constants(device->cs, WINED3D_PUSH_CONSTANTS_VS_F, start_idx, count, constants);
2528 
2529  return WINED3D_OK;
2530 }
2531 
2533  unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants)
2534 {
2535  const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
2536 
2537  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2538  device, start_idx, count, constants);
2539 
2540  if (!constants || start_idx >= d3d_info->limits.vs_uniform_count
2541  || count > d3d_info->limits.vs_uniform_count - start_idx)
2542  return WINED3DERR_INVALIDCALL;
2543 
2544  memcpy(constants, &device->state.vs_consts_f[start_idx], count * sizeof(*constants));
2545 
2546  return WINED3D_OK;
2547 }
2548 
2550 {
2551  struct wined3d_shader *prev = device->update_state->shader[WINED3D_SHADER_TYPE_PIXEL];
2552 
2553  TRACE("device %p, shader %p.\n", device, shader);
2554 
2555  if (device->recording)
2556  device->recording->changed.pixelShader = TRUE;
2557 
2558  if (shader == prev)
2559  return;
2560 
2561  if (shader)
2562  wined3d_shader_incref(shader);
2563  device->update_state->shader[WINED3D_SHADER_TYPE_PIXEL] = shader;
2564  if (!device->recording)
2566  if (prev)
2567  wined3d_shader_decref(prev);
2568 }
2569 
2571 {
2572  TRACE("device %p.\n", device);
2573 
2574  return device->state.shader[WINED3D_SHADER_TYPE_PIXEL];
2575 }
2576 
2578 {
2579  TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2580 
2582 }
2583 
2585 {
2586  TRACE("device %p, idx %u.\n", device, idx);
2587 
2589 }
2590 
2593 {
2594  TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2595 
2597 }
2598 
2600  UINT idx)
2601 {
2602  TRACE("device %p, idx %u.\n", device, idx);
2603 
2605 }
2606 
2608 {
2609  TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2610 
2612 }
2613 
2615 {
2616  TRACE("device %p, idx %u.\n", device, idx);
2617 
2619 }
2620 
2622  unsigned int start_idx, unsigned int count, const BOOL *constants)
2623 {
2624  unsigned int i;
2625 
2626  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2627  device, start_idx, count, constants);
2628 
2629  if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
2630  return WINED3DERR_INVALIDCALL;
2631 
2632  if (count > WINED3D_MAX_CONSTS_B - start_idx)
2633  count = WINED3D_MAX_CONSTS_B - start_idx;
2634  memcpy(&device->update_state->ps_consts_b[start_idx], constants, count * sizeof(*constants));
2635  if (TRACE_ON(d3d))
2636  {
2637  for (i = 0; i < count; ++i)
2638  TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]);
2639  }
2640 
2641  if (device->recording)
2642  {
2643  for (i = start_idx; i < count + start_idx; ++i)
2644  device->recording->changed.pixelShaderConstantsB |= (1u << i);
2645  }
2646  else
2647  {
2648  wined3d_cs_push_constants(device->cs, WINED3D_PUSH_CONSTANTS_PS_B, start_idx, count, constants);
2649  }
2650 
2651  return WINED3D_OK;
2652 }
2653 
2655  unsigned int start_idx, unsigned int count, BOOL *constants)
2656 {
2657  TRACE("device %p, start_idx %u, count %u,constants %p.\n",
2658  device, start_idx, count, constants);
2659 
2660  if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
2661  return WINED3DERR_INVALIDCALL;
2662 
2663  if (count > WINED3D_MAX_CONSTS_B - start_idx)
2664  count = WINED3D_MAX_CONSTS_B - start_idx;
2665  memcpy(constants, &device->state.ps_consts_b[start_idx], count * sizeof(*constants));
2666 
2667  return WINED3D_OK;
2668 }
2669 
2671  unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants)
2672 {
2673  unsigned int i;
2674 
2675  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2676  device, start_idx, count, constants);
2677 
2678  if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
2679  return WINED3DERR_INVALIDCALL;
2680 
2681  if (count > WINED3D_MAX_CONSTS_I - start_idx)
2682  count = WINED3D_MAX_CONSTS_I - start_idx;
2683  memcpy(&device->update_state->ps_consts_i[start_idx], constants, count * sizeof(*constants));
2684  if (TRACE_ON(d3d))
2685  {
2686  for (i = 0; i < count; ++i)
2687  TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i]));
2688  }
2689 
2690  if (device->recording)
2691  {
2692  for (i = start_idx; i < count + start_idx; ++i)
2693  device->recording->changed.pixelShaderConstantsI |= (1u << i);
2694  }
2695  else
2696  {
2697  wined3d_cs_push_constants(device->cs, WINED3D_PUSH_CONSTANTS_PS_I, start_idx, count, constants);
2698  }
2699 
2700  return WINED3D_OK;
2701 }
2702 
2704  unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants)
2705 {
2706  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2707  device, start_idx, count, constants);
2708 
2709  if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
2710  return WINED3DERR_INVALIDCALL;
2711 
2712  if (count > WINED3D_MAX_CONSTS_I - start_idx)
2713  count = WINED3D_MAX_CONSTS_I - start_idx;
2714  memcpy(constants, &device->state.ps_consts_i[start_idx], count * sizeof(*constants));
2715 
2716  return WINED3D_OK;
2717 }
2718 
2720  unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants)
2721 {
2722  const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
2723  unsigned int i;
2724 
2725  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2726  device, start_idx, count, constants);
2727 
2728  if (!constants || start_idx >= d3d_info->limits.ps_uniform_count
2729  || count > d3d_info->limits.ps_uniform_count - start_idx)
2730  return WINED3DERR_INVALIDCALL;
2731 
2732  memcpy(&device->update_state->ps_consts_f[start_idx], constants, count * sizeof(*constants));
2733  if (TRACE_ON(d3d))
2734  {
2735  for (i = 0; i < count; ++i)
2736  TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i]));
2737  }
2738 
2739  if (device->recording)
2740  memset(&device->recording->changed.ps_consts_f[start_idx], 1,
2741  count * sizeof(*device->recording->changed.ps_consts_f));
2742  else
2743  wined3d_cs_push_constants(device->cs, WINED3D_PUSH_CONSTANTS_PS_F, start_idx, count, constants);
2744 
2745  return WINED3D_OK;
2746 }
2747 
2749  unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants)
2750 {
2751  const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
2752 
2753  TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2754  device, start_idx, count, constants);
2755 
2756  if (!constants || start_idx >= d3d_info->limits.ps_uniform_count
2757  || count > d3d_info->limits.ps_uniform_count - start_idx)
2758  return WINED3DERR_INVALIDCALL;
2759 
2760  memcpy(constants, &device->state.ps_consts_f[start_idx], count * sizeof(*constants));
2761 
2762  return WINED3D_OK;
2763 }
2764 
2766 {
2767  struct wined3d_shader *prev;
2768 
2769  TRACE("device %p, shader %p.\n", device, shader);
2770 
2771  prev = device->update_state->shader[WINED3D_SHADER_TYPE_HULL];
2772  if (shader == prev)
2773  return;
2774  if (shader)
2775  wined3d_shader_incref(shader);
2776  device->update_state->shader[WINED3D_SHADER_TYPE_HULL] = shader;
2778  if (prev)
2779  wined3d_shader_decref(prev);
2780 }
2781 
2783 {
2784  TRACE("device %p.\n", device);
2785 
2786  return device->state.shader[WINED3D_SHADER_TYPE_HULL];
2787 }
2788 
2790 {
2791  TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2792 
2794 }
2795 
2797 {
2798  TRACE("device %p, idx %u.\n", device, idx);
2799 
2801 }
2802 
2804  unsigned int idx, struct wined3d_shader_resource_view *view)
2805 {
2806  TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2807 
2809 }
2810 
2812  unsigned int idx)
2813 {
2814  TRACE("device %p, idx %u.\n", device, idx);
2815 
2817 }
2818 
2820  unsigned int idx, struct wined3d_sampler *sampler)
2821 {
2822  TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2823 
2825 }
2826 
2828 {
2829  TRACE("device %p, idx %u.\n", device, idx);
2830 
2832 }
2833 
2835 {
2836  struct wined3d_shader *prev;
2837 
2838  TRACE("device %p, shader %p.\n", device, shader);
2839 
2840  prev = device->update_state->shader[WINED3D_SHADER_TYPE_DOMAIN];
2841  if (shader == prev)
2842  return;
2843  if (shader)
2844  wined3d_shader_incref(shader);
2845  device->update_state->shader[WINED3D_SHADER_TYPE_DOMAIN] = shader;
2847  if (prev)
2848  wined3d_shader_decref(prev);
2849 }
2850 
2852 {
2853  TRACE("device %p.\n", device);
2854 
2855  return device->state.shader[WINED3D_SHADER_TYPE_DOMAIN];
2856 }
2857 
2859 {
2860  TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2861 
2863 }
2864 
2866 {
2867  TRACE("device %p, idx %u.\n", device, idx);
2868 
2870 }
2871 
2873  unsigned int idx, struct wined3d_shader_resource_view *view)
2874 {
2875  TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2876 
2878 }
2879 
2881  unsigned int idx)
2882 {
2883  TRACE("device %p, idx %u.\n", device, idx);
2884 
2886 }
2887 
2889  unsigned int idx, struct wined3d_sampler *sampler)
2890 {
2891  TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2892 
2894 }
2895 
2897 {
2898  TRACE("device %p, idx %u.\n", device, idx);
2899 
2901 }
2902 
2904 {
2905  struct wined3d_shader *prev = device->update_state->shader[WINED3D_SHADER_TYPE_GEOMETRY];
2906 
2907  TRACE("device %p, shader %p.\n", device, shader);
2908 
2909  if (device->recording || shader == prev)
2910  return;
2911  if (shader)
2912  wined3d_shader_incref(shader);
2915  if (prev)
2916  wined3d_shader_decref(prev);
2917 }
2918 
2920 {
2921  TRACE("device %p.\n", device);
2922 
2923  return device->state.shader[WINED3D_SHADER_TYPE_GEOMETRY];
2924 }
2925 
2927 {
2928  TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2929 
2931 }
2932 
2934 {
2935  TRACE("device %p, idx %u.\n", device, idx);
2936 
2938 }
2939 
2942 {
2943  TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2944 
2946 }
2947 
2949  UINT idx)
2950 {
2951  TRACE("device %p, idx %u.\n", device, idx);
2952 
2954 }
2955 
2957 {
2958  TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2959 
2961 }
2962 
2964 {
2965  TRACE("device %p, idx %u.\n", device, idx);
2966 
2968 }
2969 
2971 {
2972  struct wined3d_shader *prev;
2973 
2974  TRACE("device %p, shader %p.\n", device, shader);
2975 
2976  prev = device->update_state->shader[WINED3D_SHADER_TYPE_COMPUTE];
2977  if (device->recording || shader == prev)
2978  return;
2979  if (shader)
2980  wined3d_shader_incref(shader);
2981  device->update_state->shader[WINED3D_SHADER_TYPE_COMPUTE] = shader;
2983  if (prev)
2984  wined3d_shader_decref(prev);
2985 }
2986 
2988 {
2989  TRACE("device %p.\n", device);
2990 
2991  return device->state.shader[WINED3D_SHADER_TYPE_COMPUTE];
2992 }
2993 
2995 {
2996  TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2997 
2999 }
3000 
3002 {
3003  TRACE("device %p, idx %u.\n", device, idx);
3004 
3006 }
3007 
3009  unsigned int idx, struct wined3d_shader_resource_view *view)
3010 {
3011  TRACE("device %p, idx %u, view %p.\n", device, idx, view);
3012 
3014 }
3015 
3017  unsigned int idx)
3018 {
3019  TRACE("device %p, idx %u.\n", device, idx);
3020 
3022 }
3023 
3025  unsigned int idx, struct wined3d_sampler *sampler)
3026 {
3027  TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
3028 
3030 }
3031 
3033 {
3034  TRACE("device %p, idx %u.\n", device, idx);
3035 
3037 }
3038 
3040  enum wined3d_pipeline pipeline, unsigned int idx, struct wined3d_unordered_access_view *uav,
3041  unsigned int initial_count)
3042 {
3043  struct wined3d_unordered_access_view *prev;
3044 
3045  if (idx >= MAX_UNORDERED_ACCESS_VIEWS)
3046  {
3047  WARN("Invalid UAV index %u.\n", idx);
3048  return;
3049  }
3050 
3051  prev = device->update_state->unordered_access_view[pipeline][idx];
3052  if (uav == prev && initial_count == ~0u)
3053  return;
3054 
3055  if (uav)
3057  device->update_state->unordered_access_view[pipeline][idx] = uav;
3058  if (!device->recording)
3059  wined3d_cs_emit_set_unordered_access_view(device->cs, pipeline, idx, uav, initial_count);
3060  if (prev)
3062 }
3063 
3065  const struct wined3d_device *device, enum wined3d_pipeline pipeline, unsigned int idx)
3066 {
3067  if (idx >= MAX_UNORDERED_ACCESS_VIEWS)
3068  {
3069  WARN("Invalid UAV index %u.\n", idx);
3070  return NULL;
3071  }
3072 
3073  return device->state.unordered_access_view[pipeline][idx];
3074 }
3075 
3077  struct wined3d_unordered_access_view *uav, unsigned int initial_count)
3078 {
3079  TRACE("device %p, idx %u, uav %p, initial_count %#x.\n", device, idx, uav, initial_count);
3080 
3082 }
3083 
3085  unsigned int idx)
3086 {
3087  TRACE("device %p, idx %u.\n", device, idx);
3088 
3090 }
3091 
3093  unsigned int idx, struct wined3d_unordered_access_view *uav, unsigned int initial_count)
3094 {
3095  TRACE("device %p, idx %u, uav %p, initial_count %#x.\n", device, idx, uav, initial_count);
3096 
3098 }
3099 
3101  const struct wined3d_device *device, unsigned int idx)
3102 {
3103  TRACE("device %p, idx %u.\n", device, idx);
3104 
3106 }
3107 
3109 {
3110  unsigned int i;
3111 
3112  if (!latency)
3113  latency = 3;
3114 
3115  device->max_frame_latency = latency;
3116  for (i = 0; i < device->swapchain_count; ++i)
3117  swapchain_set_max_frame_latency(device->swapchains[i], device);
3118 }
3119 
3121 {
3122  return device->max_frame_latency;
3123 }
3124 
3125 /* Context activation is done by the caller. */
3126 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3127 static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount,
3129  DWORD DestFVF)
3130 {
3131  struct wined3d_matrix mat, proj_mat, view_mat, world_mat;
3132  struct wined3d_map_desc map_desc;
3133  struct wined3d_box box = {0};
3134  struct wined3d_viewport vp;
3135  UINT vertex_size;
3136  unsigned int i;
3137  BYTE *dest_ptr;
3138  BOOL doClip;
3139  DWORD numTextures;
3140  HRESULT hr;
3141 
3142  if (stream_info->use_map & (1u << WINED3D_FFP_NORMAL))
3143  {
3144  WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3145  }
3146 
3147  if (!(stream_info->use_map & (1u << WINED3D_FFP_POSITION)))
3148  {
3149  ERR("Source has no position mask\n");
3150  return WINED3DERR_INVALIDCALL;
3151  }
3152 
3153  if (device->state.render_states[WINED3D_RS_CLIPPING])
3154  {
3155  static BOOL warned = FALSE;
3156  /*
3157  * The clipping code is not quite correct. Some things need
3158  * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3159  * so disable clipping for now.
3160  * (The graphics in Half-Life are broken, and my processvertices
3161  * test crashes with IDirect3DDevice3)
3162  doClip = TRUE;
3163  */
3164  doClip = FALSE;
3165  if(!warned) {
3166  warned = TRUE;
3167  FIXME("Clipping is broken and disabled for now\n");
3168  }
3169  }
3170  else
3171  doClip = FALSE;
3172 
3173  vertex_size = get_flexible_vertex_size(DestFVF);
3174  box.left = dwDestIndex * vertex_size;
3175  box.right = box.left + dwCount * vertex_size;
3176  if (FAILED(hr = wined3d_resource_map(&dest->resource, 0, &map_desc, &box, WINED3D_MAP_WRITE)))
3177  {
3178  WARN("Failed to map buffer, hr %#x.\n", hr);
3179  return hr;
3180  }
3181  dest_ptr = map_desc.data;
3182 
3183  wined3d_device_get_transform(device, WINED3D_TS_VIEW, &view_mat);
3185  wined3d_device_get_transform(device, WINED3D_TS_WORLD_MATRIX(0), &world_mat);
3186 
3187  TRACE("View mat:\n");
3188  TRACE("%.8e %.8e %.8e %.8e\n", view_mat._11, view_mat._12, view_mat._13, view_mat._14);
3189  TRACE("%.8e %.8e %.8e %.8e\n", view_mat._21, view_mat._22, view_mat._23, view_mat._24);
3190  TRACE("%.8e %.8e %.8e %.8e\n", view_mat._31, view_mat._32, view_mat._33, view_mat._34);
3191  TRACE("%.8e %.8e %.8e %.8e\n", view_mat._41, view_mat._42, view_mat._43, view_mat._44);
3192 
3193  TRACE("Proj mat:\n");
3194  TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._11, proj_mat._12, proj_mat._13, proj_mat._14);
3195  TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._21, proj_mat._22, proj_mat._23, proj_mat._24);
3196  TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._31, proj_mat._32, proj_mat._33, proj_mat._34);
3197  TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._41, proj_mat._42, proj_mat._43, proj_mat._44);
3198 
3199  TRACE("World mat:\n");
3200  TRACE("%.8e %.8e %.8e %.8e\n", world_mat._11, world_mat._12, world_mat._13, world_mat._14);
3201  TRACE("%.8e %.8e %.8e %.8e\n", world_mat._21, world_mat._22, world_mat._23, world_mat._24);
3202  TRACE("%.8e %.8e %.8e %.8e\n", world_mat._31, world_mat._32, world_mat._33, world_mat._34);
3203  TRACE("%.8e %.8e %.8e %.8e\n", world_mat._41, world_mat._42, world_mat._43, world_mat._44);
3204 
3205  /* Get the viewport */
3206  wined3d_device_get_viewports(device, NULL, &vp);
3207  TRACE("viewport x %.8e, y %.8e, width %.8e, height %.8e, min_z %.8e, max_z %.8e.\n",
3208  vp.x, vp.y, vp.width, vp.height, vp.min_z, vp.max_z);
3209 
3210  multiply_matrix(&mat,&view_mat,&world_mat);
3211  multiply_matrix(&mat,&proj_mat,&mat);
3212 
3213  numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3214 
3215  for (i = 0; i < dwCount; i+= 1) {
3216  unsigned int tex_index;
3217 
3218  if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3219  ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3220  /* The position first */
3221  const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_POSITION];
3222  const float *p = (const float *)(element->data.addr + i * element->stride);
3223  float x, y, z, rhw;
3224  TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3225 
3226  /* Multiplication with world, view and projection matrix. */
3227  x = (p[0] * mat._11) + (p[1] * mat._21) + (p[2] * mat._31) + mat._41;
3228  y = (p[0] * mat._12) + (p[1] * mat._22) + (p[2] * mat._32) + mat._42;
3229  z = (p[0] * mat._13) + (p[1] * mat._23) + (p[2] * mat._33) + mat._43;
3230  rhw = (p[0] * mat._14) + (p[1] * mat._24) + (p[2] * mat._34) + mat._44;
3231 
3232  TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3233 
3234  /* WARNING: The following things are taken from d3d7 and were not yet checked
3235  * against d3d8 or d3d9!
3236  */
3237 
3238  /* Clipping conditions: From msdn
3239  *
3240  * A vertex is clipped if it does not match the following requirements
3241  * -rhw < x <= rhw
3242  * -rhw < y <= rhw
3243  * 0 < z <= rhw
3244  * 0 < rhw ( Not in d3d7, but tested in d3d7)
3245  *
3246  * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3247  * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3248  *
3249  */
3250 
3251  if( !doClip ||
3252  ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3253  (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
3254  ( rhw > eps ) ) ) {
3255 
3256  /* "Normal" viewport transformation (not clipped)
3257  * 1) The values are divided by rhw
3258  * 2) The y axis is negative, so multiply it with -1
3259  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3260  * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3261  * 4) Multiply x with Width/2 and add Width/2
3262  * 5) The same for the height
3263  * 6) Add the viewpoint X and Y to the 2D coordinates and
3264  * The minimum Z value to z
3265  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3266  *
3267  * Well, basically it's simply a linear transformation into viewport
3268  * coordinates
3269  */
3270 
3271  x /= rhw;
3272  y /= rhw;
3273  z /= rhw;
3274 
3275  y *= -1;
3276 
3277  x *= vp.width / 2;
3278  y *= vp.height / 2;
3279  z *= vp.max_z - vp.min_z;
3280 
3281  x += vp.width / 2 + vp.x;
3282  y += vp.height / 2 + vp.y;
3283  z += vp.min_z;
3284 
3285  rhw = 1 / rhw;
3286  } else {
3287  /* That vertex got clipped
3288  * Contrary to OpenGL it is not dropped completely, it just
3289  * undergoes a different calculation.
3290  */
3291  TRACE("Vertex got clipped\n");
3292  x += rhw;
3293  y += rhw;
3294 
3295  x /= 2;
3296  y /= 2;
3297 
3298  /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3299  * outside of the main vertex buffer memory. That needs some more
3300  * investigation...
3301  */
3302  }
3303 
3304  TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3305 
3306 
3307  ( (float *) dest_ptr)[0] = x;
3308  ( (float *) dest_ptr)[1] = y;
3309  ( (float *) dest_ptr)[2] = z;
3310  ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3311 
3312  dest_ptr += 3 * sizeof(float);
3313 
3314  if ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW)
3315  dest_ptr += sizeof(float);
3316  }
3317 
3318  if (DestFVF & WINED3DFVF_PSIZE)
3319  dest_ptr += sizeof(DWORD);
3320 
3321  if (DestFVF & WINED3DFVF_NORMAL)
3322  {
3323  const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_NORMAL];
3324  const float *normal = (const float *)(element->data.addr + i * element->stride);
3325  /* AFAIK this should go into the lighting information */
3326  FIXME("Didn't expect the destination to have a normal\n");
3327  copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3328  }
3329 
3330  if (DestFVF & WINED3DFVF_DIFFUSE)
3331  {
3332  const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_DIFFUSE];
3333  const DWORD *color_d = (const DWORD *)(element->data.addr + i * element->stride);
3334  if (!(stream_info->use_map & (1u << WINED3D_FFP_DIFFUSE)))
3335  {
3336  static BOOL warned = FALSE;
3337 
3338  if(!warned) {
3339  ERR("No diffuse color in source, but destination has one\n");
3340  warned = TRUE;
3341  }
3342 
3343  *( (DWORD *) dest_ptr) = 0xffffffff;
3344  dest_ptr += sizeof(DWORD);
3345  }
3346  else
3347  {
3348  copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3349  }
3350  }
3351 
3352  if (DestFVF & WINED3DFVF_SPECULAR)
3353  {
3354  /* What's the color value in the feedback buffer? */
3355  const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_SPECULAR];
3356  const DWORD *color_s = (const DWORD *)(element->data.addr + i * element->stride);
3357  if (!(stream_info->use_map & (1u << WINED3D_FFP_SPECULAR)))
3358  {
3359  static BOOL warned = FALSE;
3360 
3361  if(!warned) {
3362  ERR("No specular color in source, but destination has one\n");
3363  warned = TRUE;
3364  }
3365 
3366  *(DWORD *)dest_ptr = 0xff000000;
3367  dest_ptr += sizeof(DWORD);
3368  }
3369  else
3370  {
3371  copy_and_next(dest_ptr, color_s, sizeof(DWORD));
3372  }
3373  }
3374 
3375  for (tex_index = 0; tex_index < numTextures; ++tex_index)
3376  {
3377  const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_TEXCOORD0 + tex_index];
3378  const float *tex_coord = (const float *)(element->data.addr + i * element->stride);
3379  if (!(stream_info->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + tex_index))))
3380  {
3381  ERR("No source texture, but destination requests one\n");
3382  dest_ptr += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3383  }
3384  else
3385  {
3386  copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3387  }
3388  }
3389  }
3390 
3391  wined3d_resource_unmap(&dest->resource, 0);
3392 
3393  return WINED3D_OK;
3394 }
3395 #undef copy_and_next
3396 
3398  UINT src_start_idx, UINT dst_idx, UINT vertex_count, struct wined3d_buffer *dst_buffer,
3399  const struct wined3d_vertex_declaration *declaration, DWORD flags, DWORD dst_fvf)
3400 {
3401  struct wined3d_state *state = &device->state;
3402  struct wined3d_stream_info stream_info;
3403  struct wined3d_resource *resource;
3404  struct wined3d_box box = {0};
3405  struct wined3d_shader *vs;
3406  unsigned int i;
3407  HRESULT hr;
3408  WORD map;
3409 
3410  TRACE("device %p, src_start_idx %u, dst_idx %u, vertex_count %u, "
3411  "dst_buffer %p, declaration %p, flags %#x, dst_fvf %#x.\n",
3412  device, src_start_idx, dst_idx, vertex_count,
3413  dst_buffer, declaration, flags, dst_fvf);
3414 
3415  if (declaration)
3416  FIXME("Output vertex declaration not implemented yet.\n");
3417 
3418  vs = state->shader[WINED3D_SHADER_TYPE_VERTEX];
3420  wined3d_stream_info_from_declaration(&stream_info, state, &device->adapter->gl_info, &device->adapter->d3d_info);
3422 
3423  /* We can't convert FROM a VBO, and vertex buffers used to source into
3424  * process_vertices() are unlikely to ever be used for drawing. Release
3425  * VBOs in those buffers and fix up the stream_info structure.
3426  *
3427  * Also apply the start index. */
3428  for (i = 0, map = stream_info.use_map; map; map >>= 1, ++i)
3429  {
3431  struct wined3d_map_desc map_desc;
3432 
3433  if (!(map & 1))
3434  continue;
3435 
3436  e = &stream_info.elements[i];
3437  resource = &state->streams[e->stream_idx].buffer->resource;
3438  box.left = src_start_idx * e->stride;
3439  box.right = box.left + vertex_count * e->stride;
3440  if (FAILED(wined3d_resource_map(resource, 0, &map_desc, &box, WINED3D_MAP_READ)))
3441  ERR("Failed to map resource.\n");
3442  e->data.buffer_object = 0;
3443  e->data.addr += (ULONG_PTR)map_desc.data;
3444  }
3445 
3446  hr = process_vertices_strided(device, dst_idx, vertex_count,
3447  &stream_info, dst_buffer, flags, dst_fvf);
3448 
3449  for (i = 0, map = stream_info.use_map; map; map >>= 1, ++i)
3450  {
3451  if (!(map & 1))
3452  continue;
3453 
3454  resource = &state->streams[stream_info.elements[i].stream_idx].buffer->resource;
3455  if (FAILED(wined3d_resource_unmap(resource, 0)))
3456  ERR("Failed to unmap resource.\n");
3457  }
3458 
3459  return hr;
3460 }
3461 
3464 {
3465  const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
3466  DWORD old_value;
3467 
3468  TRACE("device %p, stage %u, state %s, value %#x.\n",
3469  device, stage, debug_d3dtexturestate(state), value);
3470 
3471  if (state > WINED3D_HIGHEST_TEXTURE_STATE)
3472  {
3473  WARN("Invalid state %#x passed.\n", state);
3474  return;
3475  }
3476 
3477  if (stage >= d3d_info->limits.ffp_blend_stages)
3478  {
3479  WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n",
3480  stage, d3d_info->limits.ffp_blend_stages - 1);
3481  return;
3482  }
3483 
3484  old_value = device->update_state->texture_states[stage][state];
3485  device->update_state->texture_states[stage][state] = value;
3486 
3487  if (device->recording)
3488  {
3489  TRACE("Recording... not performing anything.\n");
3490  device->recording->changed.textureState[stage] |= 1u << state;
3491  return;
3492  }
3493 
3494  /* Checked after the assignments to allow proper stateblock recording. */
3495  if (old_value == value)
3496  {
3497  TRACE("Application is setting the old value over, nothing to do.\n");
3498  return;
3499  }
3500 
3501  wined3d_cs_emit_set_texture_state(device->cs, stage, state, value);
3502 }
3503 
3506 {
3507  TRACE("device %p, stage %u, state %s.\n",
3508  device, stage, debug_d3dtexturestate(state));
3509 
3510  if (state > WINED3D_HIGHEST_TEXTURE_STATE)
3511  {
3512  WARN("Invalid state %#x passed.\n", state);
3513  return 0;
3514  }
3515 
3516  return device->state.texture_states[stage][state];
3517 }
3518 
3520  UINT stage, struct wined3d_texture *texture)
3521 {
3522  struct wined3d_texture *prev;
3523 
3524  TRACE("device %p, stage %u, texture %p.\n", device, stage, texture);
3525 
3528 
3529  /* Windows accepts overflowing this array... we do not. */
3530  if (stage >= ARRAY_SIZE(device->state.textures))
3531  {
3532  WARN("Ignoring invalid stage %u.\n", stage);
3533  return WINED3D_OK;
3534  }
3535 
3536  if (texture && texture->resource.usage & WINED3DUSAGE_SCRATCH)
3537  {
3538  WARN("Rejecting attempt to set scratch texture.\n");
3539  return WINED3DERR_INVALIDCALL;
3540  }
3541 
3542  if (device->recording)
3543  device->recording->changed.textures |= 1u << stage;
3544 
3545  prev = device->update_state->textures[stage];
3546  TRACE("Previous texture %p.\n", prev);
3547 
3548  if (texture == prev)
3549  {
3550  TRACE("App is setting the same texture again, nothing to do.\n");
3551  return WINED3D_OK;
3552  }
3553 
3554  TRACE("Setting new texture to %p.\n", texture);
3555  device->update_state->textures[stage] = texture;
3556 
3557  if (texture)
3558  wined3d_texture_incref(texture);
3559  if (!device->recording)
3560  wined3d_cs_emit_set_texture(device->cs, stage, texture);
3561  if (prev)
3562  wined3d_texture_decref(prev);
3563 
3564  return WINED3D_OK;
3565 }
3566 
3568 {
3569  TRACE("device %p, stage %u.\n", device, stage);
3570 
3573 
3574  if (stage >= ARRAY_SIZE(device->state.textures))
3575  {
3576  WARN("Ignoring invalid stage %u.\n", stage);
3577  return NULL; /* Windows accepts overflowing this array ... we do not. */
3578  }
3579 
3580  return device->state.textures[stage];
3581 }
3582 
3584 {
3585  HRESULT hr;
3586 
3587  TRACE("device %p, caps %p.\n", device, caps);
3588 
3589  hr = wined3d_get_device_caps(device->wined3d, device->adapter->ordinal,
3590  device->create_parms.device_type, caps);
3591 
3592  if (SUCCEEDED(hr) && use_software_vertex_processing(device))
3593  caps->MaxVertexBlendMatrixIndex = 255;
3594 
3595  return hr;
3596 }
3597 
3599  struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation)
3600 {
3601  struct wined3d_swapchain *swapchain;
3602 
3603  TRACE("device %p, swapchain_idx %u, mode %p, rotation %p.\n",
3604  device, swapchain_idx, mode, rotation);
3605 
3606  if (!(swapchain = wined3d_device_get_swapchain(device, swapchain_idx)))
3607  return WINED3DERR_INVALIDCALL;
3608 
3609  return wined3d_swapchain_get_display_mode(swapchain, mode, rotation);
3610 }
3611 
3613 {
3614  struct wined3d_stateblock *stateblock;
3615  HRESULT hr;
3616 
3617  TRACE("device %p.\n", device);
3618 
3619  if (device->recording)
3620  return WINED3DERR_INVALIDCALL;
3621 
3622  hr = wined3d_stateblock_create(device, WINED3D_SBT_RECORDED, &stateblock);
3623  if (FAILED(hr))
3624  return hr;
3625 
3626  device->recording = stateblock;
3627  device->update_state = &stateblock->state;
3628 
3629  TRACE("Recording stateblock %p.\n", stateblock);
3630 
3631  return WINED3D_OK;
3632 }
3633 
3635  struct wined3d_stateblock **stateblock)
3636 {
3637  struct wined3d_stateblock *object = device->recording;
3638 
3639  TRACE("device %p, stateblock %p.\n", device, stateblock);
3640 
3641  if (!device->recording)
3642  {
3643  WARN("Not recording.\n");
3644  *stateblock = NULL;
3645  return WINED3DERR_INVALIDCALL;
3646  }
3647 
3649 
3650  *stateblock = object;
3651  device->recording = NULL;
3652  device->update_state = &device->state;
3653 
3654  TRACE("Returning stateblock %p.\n", *stateblock);
3655 
3656  return WINED3D_OK;
3657 }
3658 
3660 {
3661  /* At the moment we have no need for any functionality at the beginning
3662  * of a scene. */
3663  TRACE("device %p.\n", device);
3664 
3665  if (device->inScene)
3666  {
3667  WARN("Already in scene, returning WINED3DERR_INVALIDCALL.\n");
3668  return WINED3DERR_INVALIDCALL;
3669  }
3670  device->inScene = TRUE;
3671  return WINED3D_OK;
3672 }
3673 
3675 {
3676  TRACE("device %p.\n", device);
3677 
3678  if (!device->inScene)
3679  {
3680  WARN("Not in scene, returning WINED3DERR_INVALIDCALL.\n");
3681  return WINED3DERR_INVALIDCALL;
3682  }
3683 
3684  wined3d_cs_emit_flush(device->cs);
3685 
3686  device->inScene = FALSE;
3687  return WINED3D_OK;
3688 }
3689 
3691  const RECT *rects, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil)
3692 {
3693  TRACE("device %p, rect_count %u, rects %p, flags %#x, color %s, depth %.8e, stencil %u.\n",
3694  device, rect_count, rects, flags, debug_color(color), depth, stencil);
3695 
3696  if (!rect_count && rects)
3697  {
3698  WARN("Rects is %p, but rect_count is 0, ignoring clear\n", rects);
3699  return WINED3D_OK;
3700  }
3701 
3703  {
3704  struct wined3d_rendertarget_view *ds = device->fb.depth_stencil;
3705  if (!ds)
3706  {
3707  WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
3708  /* TODO: What about depth stencil buffers without stencil bits? */
3709  return WINED3DERR_INVALIDCALL;
3710  }
3711  else if (flags & WINED3DCLEAR_TARGET)
3712  {
3713  if (ds->width < device->fb.render_targets[0]->width
3714  || ds->height < device->fb.render_targets[0]->height)
3715  {
3716  WARN("Silently ignoring depth and target clear with mismatching sizes\n");
3717  return WINED3D_OK;
3718  }
3719  }
3720  }
3721 
3722  wined3d_cs_emit_clear(device->cs, rect_count, rects, flags, color, depth, stencil);
3723 
3724  return WINED3D_OK;
3725 }
3726 
3728  struct wined3d_query *predicate, BOOL value)
3729 {
3730  struct wined3d_query *prev;
3731 
3732  TRACE("device %p, predicate %p, value %#x.\n", device, predicate, value);
3733 
3734  prev = device->update_state->predicate;
3735  if (predicate)
3736  {
3737  FIXME("Predicated rendering not implemented.\n");
3738  wined3d_query_incref(predicate);
3739  }
3740  device->update_state->predicate = predicate;
3741  device->update_state->predicate_value = value;
3742  if (!device->recording)
3743  wined3d_cs_emit_set_predication(device->cs, predicate, value);
3744  if (prev)
3745  wined3d_query_decref(prev);
3746 }
3747 
3749 {
3750  TRACE("device %p, value %p.\n", device, value);
3751 
3752  if (value)
3753  *value = device->state.predicate_value;
3754  return device->state.predicate;
3755 }
3756 
3758  unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z)
3759 {
3760  TRACE("device %p, group_count_x %u, group_count_y %u, group_count_z %u.\n",
3761  device, group_count_x, group_count_y, group_count_z);
3762 
3763  wined3d_cs_emit_dispatch(device->cs, group_count_x, group_count_y, group_count_z);
3764 }
3765 
3767  struct wined3d_buffer *buffer, unsigned int offset)
3768 {
3769  TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset);
3770 
3771  wined3d_cs_emit_dispatch_indirect(device->cs, buffer, offset);
3772 }
3773 
3775  enum wined3d_primitive_type primitive_type, unsigned int patch_vertex_count)
3776 {
3777  TRACE("device %p, primitive_type %s, patch_vertex_count %u.\n",
3778  device, debug_d3dprimitivetype(primitive_type), patch_vertex_count);
3779 
3780  device->state.gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
3781  device->state.gl_patch_vertices = patch_vertex_count;
3782 }
3783 
3785  enum wined3d_primitive_type *primitive_type, unsigned int *patch_vertex_count)
3786 {
3787  TRACE("device %p, primitive_type %p, patch_vertex_count %p.\n",
3788  device, primitive_type, patch_vertex_count);
3789 
3790  *primitive_type = d3d_primitive_type_from_gl(device->state.gl_primitive_type);
3791  if (patch_vertex_count)
3792  *patch_vertex_count = device->state.gl_patch_vertices;
3793 
3794  TRACE("Returning %s.\n", debug_d3dprimitivetype(*primitive_type));
3795 }
3796 
3798 {
3799  TRACE("device %p, start_vertex %u, vertex_count %u.\n", device, start_vertex, vertex_count);
3800 
3801  wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
3802  0, start_vertex, vertex_count, 0, 0, FALSE);
3803 
3804  return WINED3D_OK;
3805 }
3806 
3808  UINT start_vertex, UINT vertex_count, UINT start_instance, UINT instance_count)
3809 {
3810  TRACE("device %p, start_vertex %u, vertex_count %u, start_instance %u, instance_count %u.\n",
3811  device, start_vertex, vertex_count, start_instance, instance_count);
3812 
3813  wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
3814  0, start_vertex, vertex_count, start_instance, instance_count, FALSE);
3815 }
3816 
3818  struct wined3d_buffer *buffer, unsigned int offset)
3819 {
3820  TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset);
3821 
3822  wined3d_cs_emit_draw_indirect(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
3823  buffer, offset, FALSE);
3824 }
3825 
3827 {
3828  TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count);
3829 
3830  if (!device->state.index_buffer)
3831  {
3832  /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
3833  * without an index buffer set. (The first time at least...)
3834  * D3D8 simply dies, but I doubt it can do much harm to return
3835  * D3DERR_INVALIDCALL there as well. */
3836  WARN("Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL.\n");
3837  return WINED3DERR_INVALIDCALL;
3838  }
3839 
3840  wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
3841  device->state.base_vertex_index, start_idx, index_count, 0, 0, TRUE);
3842 
3843  return WINED3D_OK;
3844 }
3845 
3847  UINT start_idx, UINT index_count, UINT start_instance, UINT instance_count)
3848 {
3849  TRACE("device %p, start_idx %u, index_count %u, start_instance %u, instance_count %u.\n",
3850  device, start_idx, index_count, start_instance, instance_count);
3851 
3852  wined3d_cs_emit_draw(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
3853  device->state.base_vertex_index, start_idx, index_count, start_instance, instance_count, TRUE);
3854 }
3855 
3857  struct wined3d_buffer *buffer, unsigned int offset)
3858 {
3859  TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset);
3860 
3861  wined3d_cs_emit_draw_indirect(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
3862  buffer, offset, TRUE);
3863 }
3864 
3866  struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture)
3867 {
3868  unsigned int src_size, dst_size, src_skip_levels = 0;
3869  unsigned int src_level_count, dst_level_count;
3870  unsigned int layer_count, level_count, i, j;
3871  unsigned int width, height, depth;
3873  struct wined3d_box box;
3874 
3875  TRACE("device %p, src_texture %p, dst_texture %p.\n", device, src_texture, dst_texture);
3876 
3877  /* Verify that the source and destination textures are non-NULL. */
3878  if (!src_texture || !dst_texture)
3879  {
3880  WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n");
3881  return WINED3DERR_INVALIDCALL;
3882  }
3883 
3884  if (src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU
3885  || src_texture->resource.usage & WINED3DUSAGE_SCRATCH)
3886  {
3887  WARN("Source resource is GPU accessible or a scratch resource.\n");
3888  return WINED3DERR_INVALIDCALL;
3889  }
3890  if (dst_texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU)
3891  {
3892  WARN("Destination resource is CPU accessible.\n");
3893  return WINED3DERR_INVALIDCALL;
3894  }
3895 
3896  /* Verify that the source and destination textures are the same type. */
3897  type = src_texture->resource.type;
3898  if (dst_texture->resource.type != type)
3899  {
3900  WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n");
3901  return WINED3DERR_INVALIDCALL;
3902  }
3903 
3904  layer_count = src_texture->layer_count;
3905  if (layer_count != dst_texture->layer_count)
3906  {
3907  WARN("Source and destination have different layer counts.\n");
3908  return WINED3DERR_INVALIDCALL;
3909  }
3910 
3911  if (src_texture->resource.format != dst_texture->resource.format)
3912  {
3913  WARN("Source and destination formats do not match.\n");
3914  return WINED3DERR_INVALIDCALL;
3915  }
3916 
3917  src_level_count = src_texture->level_count;
3918  dst_level_count = dst_texture->level_count;
3919  level_count = min(src_level_count, dst_level_count);
3920 
3921  src_size = max(src_texture->resource.width, src_texture->resource.height);
3922  src_size = max(src_size, src_texture->resource.depth);
3923  dst_size = max(dst_texture->resource.width, dst_texture->resource.height);
3924  dst_size = max(dst_size, dst_texture->resource.depth);
3925  while (src_size > dst_size)
3926  {
3927  src_size >>= 1;
3928  ++src_skip_levels;
3929  }
3930 
3931  if (wined3d_texture_get_level_width(src_texture, src_skip_levels) != dst_texture->resource.width
3932  || wined3d_texture_get_level_height(src_texture, src_skip_levels) != dst_texture->resource.height
3933  || wined3d_texture_get_level_depth(src_texture, src_skip_levels) != dst_texture->resource.depth)
3934  {
3935  WARN("Source and destination dimensions do not match.\n");
3936  return WINED3DERR_INVALIDCALL;
3937  }
3938 
3939  /* Update every surface level of the texture. */
3940  for (i = 0; i < level_count; ++i)
3941  {
3942  width = wined3d_texture_get_level_width(dst_texture, i);
3943  height = wined3d_texture_get_level_height(dst_texture, i);
3944  depth = wined3d_texture_get_level_depth(dst_texture, i);
3945  wined3d_box_set(&box, 0, 0, width, height, 0, depth);
3946 
3947  for (j = 0; j < layer_count; ++j)
3948  {
3950  &dst_texture->resource, j * dst_level_count + i, &box,
3951  &src_texture->resource, j * src_level_count + i + src_skip_levels, &box,
3952  0, NULL, WINED3D_TEXF_POINT);
3953  }
3954  }
3955 
3956  return WINED3D_OK;
3957 }
3958 
3960 {
3961  const struct wined3d_state *state = &device->state;
3962  struct wined3d_texture *texture;
3963  DWORD i;
3964 
3965  TRACE("device %p, num_passes %p.\n", device, num_passes);
3966 
3967  for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
3968  {
3970  {
3971  WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
3973  }
3975  {
3976  WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
3978  }
3979 
3980  texture = state->textures[i];
3981  if (!texture || texture->resource.format_flags & WINED3DFMT_FLAG_FILTERING) continue;
3982 
3984  {
3985  WARN("Non-filterable texture and mag filter enabled on sampler %u, returning E_FAIL\n", i);
3986  return E_FAIL;
3987  }
3989  {
3990  WARN("Non-filterable texture and min filter enabled on sampler %u, returning E_FAIL\n", i);
3991  return E_FAIL;
3992  }
3995  {
3996  WARN("Non-filterable texture and mip filter enabled on sampler %u, returning E_FAIL\n", i);
3997  return E_FAIL;
3998  }
3999  }
4000 
4003  {
4004  struct wined3d_rendertarget_view *rt = device->fb.render_targets[0];
4005  struct wined3d_rendertarget_view *ds = device->fb.depth_stencil;
4006 
4007  if (ds && rt && (ds->width < rt->width || ds->height < rt->height))
4008  {
4009  WARN("Depth stencil is smaller than the color buffer, returning D3DERR_CONFLICTINGRENDERSTATE\n");
4011  }
4012  }
4013 
4014  /* return a sensible default */
4015  *num_passes = 1;
4016 
4017  TRACE("returning D3D_OK\n");
4018  return WINED3D_OK;
4019 }
4020 
4022 {
4023  TRACE("device %p, software %#x.\n", device, software);
4024 
4025  device->softwareVertexProcessing = software;
4026 }
4027 
4029 {
4030  TRACE("device %p.\n", device);
4031 
4032  return device->softwareVertexProcessing;
4033 }
4034 
4036  UINT swapchain_idx, struct wined3d_raster_status *raster_status)
4037 {
4038  struct wined3d_swapchain *swapchain;
4039 
4040  TRACE("device %p, swapchain_idx %u, raster_status %p.\n",
4041  device, swapchain_idx, raster_status);
4042 
4043  if (!(swapchain = wined3d_device_get_swapchain(device, swapchain_idx)))
4044  return WINED3DERR_INVALIDCALL;
4045 
4046  return wined3d_swapchain_get_raster_status(swapchain, raster_status);
4047 }
4048 
4050 {
4051  static BOOL warned;
4052 
4053  TRACE("device %p, segments %.8e.\n", device, segments);
4054 
4055  if (segments != 0.0f)
4056  {
4057  if (!warned)
4058  {
4059  FIXME("device %p, segments %.8e stub!\n", device, segments);
4060  warned = TRUE;
4061  }
4062  }
4063 
4064  return WINED3D_OK;
4065 }
4066 
4068 {
4069  static BOOL warned;
4070 
4071  TRACE("device %p.\n", device);
4072 
4073  if (!warned)
4074  {
4075  FIXME("device %p stub!\n", device);
4076  warned = TRUE;
4077  }
4078 
4079  return 0.0f;
4080 }
4081 
4083  struct wined3d_buffer *dst_buffer, unsigned int offset, struct wined3d_unordered_access_view *uav)
4084 {
4085  TRACE("device %p, dst_buffer %p, offset %u, uav %p.\n",
4086  device, dst_buffer, offset, uav);
4087 
4088  if (offset + sizeof(GLuint) > dst_buffer->resource.size)
4089  {
4090  WARN("Offset %u too large.\n", offset);
4091  return;
4092  }
4093 
4094  wined3d_cs_emit_copy_uav_counter(device->cs, dst_buffer, offset, uav);
4095 }
4096 
4098  struct wined3d_resource *dst_resource, struct wined3d_resource *src_resource)
4099 {
4100  struct wined3d_texture *dst_texture, *src_texture;
4101  struct wined3d_box box;
4102  unsigned int i, j;
4103 
4104  TRACE("device %p, dst_resource %p, src_resource %p.\n", device, dst_resource, src_resource);
4105 
4106  if (src_resource == dst_resource)
4107  {
4108  WARN("Source and destination are the same resource.\n");
4109  return;
4110  }
4111 
4112  if (src_resource->type != dst_resource->type)
4113  {
4114  WARN("Resource types (%s / %s) don't match.\n",
4115  debug_d3dresourcetype(dst_resource->type),
4116  debug_d3dresourcetype(src_resource->type));
4117  return;
4118  }
4119 
4120  if (src_resource->width != dst_resource->width
4121  || src_resource->height != dst_resource->height
4122  || src_resource->depth != dst_resource->depth)
4123  {
4124  WARN("Resource dimensions (%ux%ux%u / %ux%ux%u) don't match.\n",
4125  dst_resource->width, dst_resource->height, dst_resource->depth,
4126  src_resource->width, src_resource->height, src_resource->depth);
4127  return;
4128  }
4129 
4130  if (src_resource->format->typeless_id != dst_resource->format->typeless_id
4131  || (!src_resource->format->typeless_id && src_resource->format->id != dst_resource->format->id))
4132  {
4133  WARN("Resource formats %s and %s are incompatible.\n",
4134  debug_d3dformat(dst_resource->format->id),
4135  debug_d3dformat(src_resource->format->id));
4136  return;
4137  }
4138 
4139  if (dst_resource->type == WINED3D_RTYPE_BUFFER)
4140  {
4141  wined3d_box_set(&box, 0, 0, src_resource->size, 1, 0, 1);
4142  wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, 0, &box,
4143  src_resource, 0, &box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT);
4144  return;
4145  }
4146 
4147  dst_texture = texture_from_resource(dst_resource);
4148  src_texture = texture_from_resource(src_resource);
4149 
4150  if (src_texture->layer_count != dst_texture->layer_count
4151  || src_texture->level_count != dst_texture->level_count)
4152  {
4153  WARN("Subresource layouts (%ux%u / %ux%u) don't match.\n",
4154  dst_texture->layer_count, dst_texture->level_count,
4155  src_texture->layer_count, src_texture->level_count);
4156  return;
4157  }
4158 
4159  for (i = 0; i < dst_texture->level_count; ++i)
4160  {
4161  wined3d_box_set(&box, 0, 0,
4162  wined3d_texture_get_level_width(dst_texture, i),
4163  wined3d_texture_get_level_height(dst_texture, i),
4164  0, wined3d_texture_get_level_depth(dst_texture, i));
4165  for (j = 0; j < dst_texture->layer_count; ++j)
4166  {
4167  unsigned int idx = j * dst_texture->level_count + i;
4168 
4169  wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, idx, &box,
4170  src_resource, idx, &box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT);
4171  }
4172  }
4173 }
4174 
4176  struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, unsigned int dst_x,
4177  unsigned int dst_y, unsigned int dst_z, struct wined3d_resource *src_resource,
4178  unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, unsigned int flags)
4179 {
4180  struct wined3d_box dst_box, b;
4181 
4182  TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, "
4183  "src_resource %p, src_sub_resource_idx %u, src_box %s, flags %#x.\n",
4184  device, dst_resource, dst_sub_resource_idx, dst_x, dst_y, dst_z,
4185  src_resource, src_sub_resource_idx, debug_box(src_box), flags);
4186 
4187  if (flags)
4188  FIXME("Ignoring flags %#x.\n", flags);
4189 
4190  if (src_resource == dst_resource && src_sub_resource_idx == dst_sub_resource_idx)
4191  {
4192  WARN("Source and destination are the same sub-resource.\n");
4193  return WINED3DERR_INVALIDCALL;
4194  }
4195 
4196  if (src_resource->type != dst_resource->type)
4197  {
4198  WARN("Resource types (%s / %s) don't match.\n",
4199  debug_d3dresourcetype(dst_resource->type),
4200  debug_d3dresourcetype(src_resource->type));
4201  return WINED3DERR_INVALIDCALL;
4202  }
4203 
4204  if (src_resource->format->typeless_id != dst_resource->format->typeless_id
4205  || (!src_resource->format->typeless_id && src_resource->format->id != dst_resource->format->id))
4206  {
4207  WARN("Resource formats %s and %s are incompatible.\n",
4208  debug_d3dformat(dst_resource->format->id),
4209  debug_d3dformat(src_resource->format->id));
4210  return WINED3DERR_INVALIDCALL;
4211  }
4212 
4213  if (dst_resource->type == WINED3D_RTYPE_BUFFER)
4214  {
4215  if (dst_sub_resource_idx)
4216  {
4217  WARN("Invalid dst_sub_resource_idx %u.\n", dst_sub_resource_idx);
4218  return WINED3DERR_INVALIDCALL;
4219  }
4220 
4221  if (src_sub_resource_idx)
4222  {
4223  WARN("Invalid src_sub_resource_idx %u.\n", src_sub_resource_idx);
4224  return WINED3DERR_INVALIDCALL;
4225  }
4226 
4227  if (!src_box)
4228  {
4229  unsigned int dst_w;
4230 
4231  dst_w = dst_resource->size - dst_x;
4232  wined3d_box_set(&b, 0, 0, min(src_resource->size, dst_w), 1, 0, 1);
4233  src_box = &b;
4234  }
4235  else if ((src_box->left >= src_box->right
4236  || src_box->top >= src_box->bottom
4237  || src_box->front >= src_box->back))
4238  {
4239  WARN("Invalid box %s specified.\n", debug_box(src_box));
4240  return WINED3DERR_INVALIDCALL;
4241  }
4242 
4243  if (src_box->right > src_resource->size || dst_x >= dst_resource->size
4244  || src_box->right - src_box->left > dst_resource->size - dst_x)
4245  {
4246  WARN("Invalid range specified, dst_offset %u, src_offset %u, size %u.\n",
4247  dst_x, src_box->left, src_box->right - src_box->left);
4248  return WINED3DERR_INVALIDCALL;
4249  }
4250 
4251  wined3d_box_set(&dst_box, dst_x, 0, dst_x + (src_box->right - src_box->left), 1, 0, 1);
4252  }
4253  else
4254  {
4255  struct wined3d_texture *dst_texture = texture_from_resource(dst_resource);
4256  struct wined3d_texture *src_texture = texture_from_resource(src_resource);
4257  unsigned int src_level = src_sub_resource_idx % src_texture->level_count;
4258 
4259  if (dst_sub_resource_idx >= dst_texture->level_count * dst_texture->layer_count)
4260  {
4261  WARN("Invalid destination sub-resource %u.\n", dst_sub_resource_idx);
4262  return WINED3DERR_INVALIDCALL;
4263  }
4264 
4265  if (src_sub_resource_idx >= src_texture->level_count * src_texture->layer_count)
4266  {
4267  WARN("Invalid source sub-resource %u.\n", src_sub_resource_idx);
4268  return WINED3DERR_INVALIDCALL;
4269  }
4270 
4271  if (dst_texture->sub_resources[dst_sub_resource_idx].map_count)
4272  {
4273  WARN("Destination sub-resource %u is mapped.\n", dst_sub_resource_idx);
4274  return WINED3DERR_INVALIDCALL;
4275  }
4276 
4277  if (src_texture->sub_resources[src_sub_resource_idx].map_count)
4278  {
4279  WARN("Source sub-resource %u is mapped.\n", src_sub_resource_idx);
4280  return WINED3DERR_INVALIDCALL;
4281  }
4282 
4283  if (!src_box)
4284  {
4285  unsigned int src_w, src_h, src_d, dst_w, dst_h, dst_d, dst_level;
4286 
4287  src_w = wined3d_texture_get_level_width(src_texture, src_level);
4288  src_h = wined3d_texture_get_level_height(src_texture, src_level);
4289  src_d = wined3d_texture_get_level_depth(src_texture, src_level);
4290 
4291  dst_level = dst_sub_resource_idx % dst_texture->level_count;
4292  dst_w = wined3d_texture_get_level_width(dst_texture, dst_level) - dst_x;
4293  dst_h = wined3d_texture_get_level_height(dst_texture, dst_level) - dst_y;
4294  dst_d = wined3d_texture_get_level_depth(dst_texture, dst_level) - dst_z;
4295 
4296  wined3d_box_set(&b, 0, 0, min(src_w, dst_w), min(src_h, dst_h), 0, min(src_d, dst_d));
4297  src_box = &b;
4298  }
4299  else if (FAILED(wined3d_texture_check_box_dimensions(src_texture, src_level, src_box)))
4300  {
4301  WARN("Invalid source box %s.\n", debug_box(src_box));
4302  return WINED3DERR_INVALIDCALL;
4303  }
4304 
4305  wined3d_box_set(&dst_box, dst_x, dst_y, dst_x + (src_box->right - src_box->left),
4306  dst_y + (src_box->bottom - src_box->top), dst_z, dst_z + (src_box->back - src_box->front));
4308  dst_sub_resource_idx % dst_texture->level_count, &dst_box)))
4309  {
4310  WARN("Invalid destination box %s.\n", debug_box(&dst_box));
4311  return WINED3DERR_INVALIDCALL;
4312  }
4313  }
4314 
4315  wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, dst_sub_resource_idx, &dst_box,
4316  src_resource, src_sub_resource_idx, src_box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT);
4317 
4318  return WINED3D_OK;
4319 }
4320 
4322  unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
4323  unsigned int depth_pitch, unsigned int flags)
4324 {
4325  unsigned int width, height, depth;
4326  struct wined3d_box b;
4327 
4328  TRACE("device %p, resource %p, sub_resource_idx %u, box %s, data %p, row_pitch %u, depth_pitch %u, "
4329  "flags %#x.\n",
4330  device, resource, sub_resource_idx, debug_box(box), data, row_pitch, depth_pitch, flags);
4331 
4332  if (flags)
4333  FIXME("Ignoring flags %#x.\n", flags);
4334 
4335  if (resource->type == WINED3D_RTYPE_BUFFER)
4336  {
4337  if (sub_resource_idx > 0)
4338  {
4339  WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
4340  return;
4341  }
4342 
4343  width = resource->size;
4344  height = 1;
4345  depth = 1;
4346  }
4347  else
4348  {
4349  struct wined3d_texture *texture = texture_from_resource(resource);
4350  unsigned int level;
4351 
4352  if (sub_resource_idx >= texture->level_count * texture->layer_count)
4353  {
4354  WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
4355  return;
4356  }
4357 
4358  level = sub_resource_idx % texture->level_count;
4359  width = wined3d_texture_get_level_width(texture, level);
4360  height = wined3d_texture_get_level_height(texture, level);
4361  depth = wined3d_texture_get_level_depth(texture, level);
4362  }
4363 
4364  if (!box)
4365  {
4366  wined3d_box_set(&b, 0, 0, width, height, 0, depth);
4367  box = &b;
4368  }
4369  else if (box->left >= box->right || box->right > width
4370  || box->top >= box->bottom || box->bottom > height
4371  || box->front >= box->back || box->back > depth)
4372  {
4373  WARN("Invalid box %s specified.\n", debug_box(box));
4374  return;
4375  }
4376 
4377  wined3d_cs_emit_update_sub_resource(device->cs, resource, sub_resource_idx, box, data, row_pitch, depth_pitch);
4378 }
4379 
4381  struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx,
4382  struct wined3d_resource *src_resource, unsigned int src_sub_resource_idx,
4384 {
4385  struct wined3d_texture *dst_texture, *src_texture;
4386  unsigned int dst_level, src_level;
4387  RECT dst_rect, src_rect;
4388 
4389  TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, "
4390  "src_resource %p, src_sub_resource_idx %u, format %s.\n",
4391  device, dst_resource, dst_sub_resource_idx,
4392  src_resource, src_sub_resource_idx, debug_d3dformat(format_id));
4393 
4394  if (wined3d_format_is_typeless(dst_resource->format)
4395  || wined3d_format_is_typeless(src_resource->format))
4396