ReactOS  0.4.13-dev-563-g0561610
device.c
Go to the documentation of this file.
1 /*
2  * IDirect3DDevice9 implementation
3  *
4  * Copyright 2002-2005 Jason Edmeades
5  * Copyright 2002-2005 Raphael Junqueira
6  * Copyright 2005 Oliver Stieber
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #include "config.h"
24 #include "d3d9_private.h"
25 
27 
29 
31 {
33 };
34 
36 {
37  BYTE *c = (BYTE *)&format;
38 
39  /* Don't translate FOURCC formats */
40  if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
41 
42  switch(format)
43  {
53  case WINED3DFMT_A8_UNORM: return D3DFMT_A8;
63  case WINED3DFMT_P8_UINT: return D3DFMT_P8;
64  case WINED3DFMT_L8_UNORM: return D3DFMT_L8;
74  case WINED3DFMT_D32_UNORM: return D3DFMT_D32;
79  case WINED3DFMT_D16_UNORM: return D3DFMT_D16;
80  case WINED3DFMT_L16_UNORM: return D3DFMT_L16;
86  case WINED3DFMT_R16_FLOAT: return D3DFMT_R16F;
89  case WINED3DFMT_R32_FLOAT: return D3DFMT_R32F;
93  default:
94  FIXME("Unhandled wined3d format %#x.\n", format);
95  return D3DFMT_UNKNOWN;
96  }
97 }
98 
100 {
101  BYTE *c = (BYTE *)&format;
102 
103  /* Don't translate FOURCC formats */
104  if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
105 
106  switch(format)
107  {
108  case D3DFMT_UNKNOWN: return WINED3DFMT_UNKNOWN;
117  case D3DFMT_A8: return WINED3DFMT_A8_UNORM;
127  case D3DFMT_P8: return WINED3DFMT_P8_UINT;
128  case D3DFMT_L8: return WINED3DFMT_L8_UNORM;
129  case D3DFMT_A8L8: return WINED3DFMT_L8A8_UNORM;
130  case D3DFMT_A4L4: return WINED3DFMT_L4A4_UNORM;
131  case D3DFMT_V8U8: return WINED3DFMT_R8G8_SNORM;
138  case D3DFMT_D32: return WINED3DFMT_D32_UNORM;
143  case D3DFMT_D16: return WINED3DFMT_D16_UNORM;
144  case D3DFMT_L16: return WINED3DFMT_L16_UNORM;
147  case D3DFMT_INDEX16: return WINED3DFMT_R16_UINT;
148  case D3DFMT_INDEX32: return WINED3DFMT_R32_UINT;
150  case D3DFMT_R16F: return WINED3DFMT_R16_FLOAT;
153  case D3DFMT_R32F: return WINED3DFMT_R32_FLOAT;
157  default:
158  FIXME("Unhandled D3DFORMAT %#x.\n", format);
159  return WINED3DFMT_UNKNOWN;
160  }
161 }
162 
163 unsigned int wined3dmapflags_from_d3dmapflags(unsigned int flags)
164 {
165  static const unsigned int handled = D3DLOCK_NOSYSLOCK
170  unsigned int wined3d_flags;
171 
172  wined3d_flags = flags & handled;
174  wined3d_flags |= WINED3D_MAP_READ;
175  if (!(flags & D3DLOCK_READONLY))
176  wined3d_flags |= WINED3D_MAP_WRITE;
177  if (!(wined3d_flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE)))
178  wined3d_flags |= WINED3D_MAP_READ | WINED3D_MAP_WRITE;
179  flags &= ~(handled | D3DLOCK_READONLY);
180 
181  if (flags)
182  FIXME("Unhandled flags %#x.\n", flags);
183 
184  return wined3d_flags;
185 }
186 
187 static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, UINT primitive_count)
188 {
189  switch (primitive_type)
190  {
191  case D3DPT_POINTLIST:
192  return primitive_count;
193 
194  case D3DPT_LINELIST:
195  return primitive_count * 2;
196 
197  case D3DPT_LINESTRIP:
198  return primitive_count + 1;
199 
200  case D3DPT_TRIANGLELIST:
201  return primitive_count * 3;
202 
203  case D3DPT_TRIANGLESTRIP:
204  case D3DPT_TRIANGLEFAN:
205  return primitive_count + 2;
206 
207  default:
208  FIXME("Unhandled primitive type %#x.\n", primitive_type);
209  return 0;
210  }
211 }
212 
214 {
215  switch (effect)
216  {
218  return D3DSWAPEFFECT_DISCARD;
220  return D3DSWAPEFFECT_FLIP;
222  return D3DSWAPEFFECT_COPY;
224  return D3DSWAPEFFECT_OVERLAY;
226  return D3DSWAPEFFECT_FLIPEX;
227  default:
228  FIXME("Unhandled swap effect %#x.\n", effect);
229  return D3DSWAPEFFECT_FLIP;
230  }
231 }
232 
234  const struct wined3d_swapchain_desc *swapchain_desc, DWORD presentation_interval)
235 {
236  present_parameters->BackBufferWidth = swapchain_desc->backbuffer_width;
237  present_parameters->BackBufferHeight = swapchain_desc->backbuffer_height;
238  present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc->backbuffer_format);
239  present_parameters->BackBufferCount = swapchain_desc->backbuffer_count;
240  present_parameters->MultiSampleType = swapchain_desc->multisample_type;
241  present_parameters->MultiSampleQuality = swapchain_desc->multisample_quality;
242  present_parameters->SwapEffect = d3dswapeffect_from_wined3dswapeffect(swapchain_desc->swap_effect);
243  present_parameters->hDeviceWindow = swapchain_desc->device_window;
244  present_parameters->Windowed = swapchain_desc->windowed;
245  present_parameters->EnableAutoDepthStencil = swapchain_desc->enable_auto_depth_stencil;
246  present_parameters->AutoDepthStencilFormat
248  present_parameters->Flags = swapchain_desc->flags & D3DPRESENTFLAGS_MASK;
249  present_parameters->FullScreen_RefreshRateInHz = swapchain_desc->refresh_rate;
250  present_parameters->PresentationInterval = presentation_interval;
251 }
252 
254 {
255  switch (effect)
256  {
259  case D3DSWAPEFFECT_FLIP:
261  case D3DSWAPEFFECT_COPY:
267  default:
268  FIXME("Unhandled swap effect %#x.\n", effect);
270  }
271 }
272 
274 {
275  switch (interval)
276  {
287  default:
288  FIXME("Unhandled presentation interval %#x.\n", interval);
291  }
292 }
293 
295  const D3DPRESENT_PARAMETERS *present_parameters, BOOL extended)
296 {
297  D3DSWAPEFFECT highest_swapeffect = extended ? D3DSWAPEFFECT_FLIPEX : D3DSWAPEFFECT_COPY;
298  UINT highest_bb_count = extended ? 30 : 3;
299 
300  if (!present_parameters->SwapEffect || present_parameters->SwapEffect > highest_swapeffect)
301  {
302  WARN("Invalid swap effect %u passed.\n", present_parameters->SwapEffect);
303  return FALSE;
304  }
305  if (present_parameters->BackBufferCount > highest_bb_count
306  || (present_parameters->SwapEffect == D3DSWAPEFFECT_COPY
307  && present_parameters->BackBufferCount > 1))
308  {
309  WARN("Invalid backbuffer count %u.\n", present_parameters->BackBufferCount);
310  return FALSE;
311  }
312  switch (present_parameters->PresentationInterval)
313  {
320  break;
321  default:
322  WARN("Invalid presentation interval %#x.\n", present_parameters->PresentationInterval);
323  return FALSE;
324  }
325 
326  swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth;
327  swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight;
328  swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat);
329  swapchain_desc->backbuffer_count = max(1, present_parameters->BackBufferCount);
331  swapchain_desc->multisample_type = present_parameters->MultiSampleType;
332  swapchain_desc->multisample_quality = present_parameters->MultiSampleQuality;
333  swapchain_desc->swap_effect = wined3dswapeffect_from_d3dswapeffect(present_parameters->SwapEffect);
334  swapchain_desc->device_window = present_parameters->hDeviceWindow;
335  swapchain_desc->windowed = present_parameters->Windowed;
336  swapchain_desc->enable_auto_depth_stencil = present_parameters->EnableAutoDepthStencil;
337  swapchain_desc->auto_depth_stencil_format
339  swapchain_desc->flags
341  swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz;
342  swapchain_desc->auto_restore_display_mode = TRUE;
343 
344  if (present_parameters->Flags & ~D3DPRESENTFLAGS_MASK)
345  FIXME("Unhandled flags %#x.\n", present_parameters->Flags & ~D3DPRESENTFLAGS_MASK);
346 
347  return TRUE;
348 }
349 
350 void d3dcaps_from_wined3dcaps(D3DCAPS9 *caps, const WINED3DCAPS *wined3d_caps)
351 {
352  static const DWORD ps_minor_version[] = {0, 4, 0, 0};
353  static const DWORD vs_minor_version[] = {0, 1, 0, 0};
354  static const DWORD texture_filter_caps =
360 
361  caps->DeviceType = (D3DDEVTYPE)wined3d_caps->DeviceType;
362  caps->AdapterOrdinal = wined3d_caps->AdapterOrdinal;
363  caps->Caps = wined3d_caps->Caps;
364  caps->Caps2 = wined3d_caps->Caps2;
365  caps->Caps3 = wined3d_caps->Caps3;
367  caps->CursorCaps = wined3d_caps->CursorCaps;
368  caps->DevCaps = wined3d_caps->DevCaps;
369  caps->PrimitiveMiscCaps = wined3d_caps->PrimitiveMiscCaps;
370  caps->RasterCaps = wined3d_caps->RasterCaps;
371  caps->ZCmpCaps = wined3d_caps->ZCmpCaps;
372  caps->SrcBlendCaps = wined3d_caps->SrcBlendCaps;
373  caps->DestBlendCaps = wined3d_caps->DestBlendCaps;
374  caps->AlphaCmpCaps = wined3d_caps->AlphaCmpCaps;
375  caps->ShadeCaps = wined3d_caps->ShadeCaps;
376  caps->TextureCaps = wined3d_caps->TextureCaps;
377  caps->TextureFilterCaps = wined3d_caps->TextureFilterCaps;
378  caps->CubeTextureFilterCaps = wined3d_caps->CubeTextureFilterCaps;
379  caps->VolumeTextureFilterCaps = wined3d_caps->VolumeTextureFilterCaps;
380  caps->TextureAddressCaps = wined3d_caps->TextureAddressCaps;
382  caps->LineCaps = wined3d_caps->LineCaps;
383  caps->MaxTextureWidth = wined3d_caps->MaxTextureWidth;
384  caps->MaxTextureHeight = wined3d_caps->MaxTextureHeight;
385  caps->MaxVolumeExtent = wined3d_caps->MaxVolumeExtent;
386  caps->MaxTextureRepeat = wined3d_caps->MaxTextureRepeat;
387  caps->MaxTextureAspectRatio = wined3d_caps->MaxTextureAspectRatio;
388  caps->MaxAnisotropy = wined3d_caps->MaxAnisotropy;
389  caps->MaxVertexW = wined3d_caps->MaxVertexW;
390  caps->GuardBandLeft = wined3d_caps->GuardBandLeft;
391  caps->GuardBandTop = wined3d_caps->GuardBandTop;
392  caps->GuardBandRight = wined3d_caps->GuardBandRight;
393  caps->GuardBandBottom = wined3d_caps->GuardBandBottom;
394  caps->ExtentsAdjust = wined3d_caps->ExtentsAdjust;
395  caps->StencilCaps = wined3d_caps->StencilCaps;
396  caps->FVFCaps = wined3d_caps->FVFCaps;
397  caps->TextureOpCaps = wined3d_caps->TextureOpCaps;
398  caps->MaxTextureBlendStages = wined3d_caps->MaxTextureBlendStages;
399  caps->MaxSimultaneousTextures = wined3d_caps->MaxSimultaneousTextures;
400  caps->VertexProcessingCaps = wined3d_caps->VertexProcessingCaps;
401  caps->MaxActiveLights = wined3d_caps->MaxActiveLights;
402  caps->MaxUserClipPlanes = wined3d_caps->MaxUserClipPlanes;
403  caps->MaxVertexBlendMatrices = wined3d_caps->MaxVertexBlendMatrices;
405  caps->MaxPointSize = wined3d_caps->MaxPointSize;
406  caps->MaxPrimitiveCount = wined3d_caps->MaxPrimitiveCount;
407  caps->MaxVertexIndex = wined3d_caps->MaxVertexIndex;
408  caps->MaxStreams = wined3d_caps->MaxStreams;
409  caps->MaxStreamStride = wined3d_caps->MaxStreamStride;
410  caps->VertexShaderVersion = wined3d_caps->VertexShaderVersion;
411  caps->MaxVertexShaderConst = wined3d_caps->MaxVertexShaderConst;
412  caps->PixelShaderVersion = wined3d_caps->PixelShaderVersion;
413  caps->PixelShader1xMaxValue = wined3d_caps->PixelShader1xMaxValue;
414  caps->DevCaps2 = wined3d_caps->DevCaps2;
416  caps->MasterAdapterOrdinal = wined3d_caps->MasterAdapterOrdinal;
417  caps->AdapterOrdinalInGroup = wined3d_caps->AdapterOrdinalInGroup;
418  caps->NumberOfAdaptersInGroup = wined3d_caps->NumberOfAdaptersInGroup;
419  caps->DeclTypes = wined3d_caps->DeclTypes;
420  caps->NumSimultaneousRTs = wined3d_caps->NumSimultaneousRTs;
421  caps->StretchRectFilterCaps = wined3d_caps->StretchRectFilterCaps;
422  caps->VS20Caps.Caps = wined3d_caps->VS20Caps.caps;
423  caps->VS20Caps.DynamicFlowControlDepth = wined3d_caps->VS20Caps.dynamic_flow_control_depth;
424  caps->VS20Caps.NumTemps = wined3d_caps->VS20Caps.temp_count;
425  caps->VS20Caps.StaticFlowControlDepth = wined3d_caps->VS20Caps.static_flow_control_depth;
426  caps->PS20Caps.Caps = wined3d_caps->PS20Caps.caps;
427  caps->PS20Caps.DynamicFlowControlDepth = wined3d_caps->PS20Caps.dynamic_flow_control_depth;
428  caps->PS20Caps.NumTemps = wined3d_caps->PS20Caps.temp_count;
429  caps->PS20Caps.StaticFlowControlDepth = wined3d_caps->PS20Caps.static_flow_control_depth;
430  caps->PS20Caps.NumInstructionSlots = wined3d_caps->PS20Caps.instruction_slot_count;
431  caps->VertexTextureFilterCaps = wined3d_caps->VertexTextureFilterCaps;
436 
437  /* Some functionality is implemented in d3d9.dll, not wined3d.dll. Add the needed caps. */
439 
440  /* Filter wined3d caps. */
441  caps->TextureFilterCaps &= texture_filter_caps;
442  caps->CubeTextureFilterCaps &= texture_filter_caps;
443  caps->VolumeTextureFilterCaps &= texture_filter_caps;
444 
445  caps->DevCaps &=
453 
454  caps->ShadeCaps &=
457 
458  caps->RasterCaps &=
465 
466  caps->DevCaps2 &=
470 
471  caps->Caps2 &=
474 
475  caps->VertexProcessingCaps &=
479 
480  caps->TextureCaps &=
487 
490 
491  if (caps->PixelShaderVersion > 3)
492  {
493  caps->PixelShaderVersion = D3DPS_VERSION(3, 0);
494  }
495  else
496  {
498  caps->PixelShaderVersion = D3DPS_VERSION(major, ps_minor_version[major]);
499  }
500 
501  if (caps->VertexShaderVersion > 3)
502  {
503  caps->VertexShaderVersion = D3DVS_VERSION(3, 0);
504  }
505  else
506  {
508  caps->VertexShaderVersion = D3DVS_VERSION(major, vs_minor_version[major]);
509  }
510 }
511 
512 static HRESULT WINAPI d3d9_device_QueryInterface(IDirect3DDevice9Ex *iface, REFIID riid, void **out)
513 {
514  TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
515 
516  if (IsEqualGUID(riid, &IID_IDirect3DDevice9)
518  {
520  *out = iface;
521  return S_OK;
522  }
523 
524  if (IsEqualGUID(riid, &IID_IDirect3DDevice9Ex))
525  {
527 
528  /* Find out if the creating d3d9 interface was created with Direct3DCreate9Ex.
529  * It doesn't matter with which function the device was created. */
530  if (!device->d3d_parent->extended)
531  {
532  WARN("IDirect3D9 instance wasn't created with CreateDirect3D9Ex, returning E_NOINTERFACE.\n");
533  *out = NULL;
534  return E_NOINTERFACE;
535  }
536 
538  *out = iface;
539  return S_OK;
540  }
541 
542  WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
543 
544  *out = NULL;
545  return E_NOINTERFACE;
546 }
547 
548 static ULONG WINAPI d3d9_device_AddRef(IDirect3DDevice9Ex *iface)
549 {
552 
553  TRACE("%p increasing refcount to %u.\n", iface, refcount);
554 
555  return refcount;
556 }
557 
558 static ULONG WINAPI DECLSPEC_HOTPATCH d3d9_device_Release(IDirect3DDevice9Ex *iface)
559 {
561  ULONG refcount;
562 
563  if (device->in_destruction)
564  return 0;
565 
566  refcount = InterlockedDecrement(&device->refcount);
567 
568  TRACE("%p decreasing refcount to %u.\n", iface, refcount);
569 
570  if (!refcount)
571  {
572  unsigned i;
573  device->in_destruction = TRUE;
574 
576  for (i = 0; i < device->fvf_decl_count; ++i)
577  {
578  wined3d_vertex_declaration_decref(device->fvf_decls[i].decl);
579  }
580  heap_free(device->fvf_decls);
581 
582  if (device->vertex_buffer)
583  wined3d_buffer_decref(device->vertex_buffer);
584  if (device->index_buffer)
585  wined3d_buffer_decref(device->index_buffer);
586 
587  heap_free(device->implicit_swapchains);
588 
589  wined3d_device_uninit_3d(device->wined3d_device);
591  wined3d_device_decref(device->wined3d_device);
593 
594  IDirect3D9Ex_Release(&device->d3d_parent->IDirect3D9Ex_iface);
595 
596  heap_free(device);
597  }
598 
599  return refcount;
600 }
601 
602 static HRESULT WINAPI d3d9_device_TestCooperativeLevel(IDirect3DDevice9Ex *iface)
603 {
605 
606  TRACE("iface %p.\n", iface);
607 
608  TRACE("device state: %#x.\n", device->device_state);
609 
610  if (device->d3d_parent->extended)
611  return D3D_OK;
612 
613  switch (device->device_state)
614  {
615  default:
617  return D3D_OK;
619  return D3DERR_DEVICELOST;
621  return D3DERR_DEVICENOTRESET;
622  }
623 }
624 
625 static UINT WINAPI d3d9_device_GetAvailableTextureMem(IDirect3DDevice9Ex *iface)
626 {
628  UINT ret;
629 
630  TRACE("iface %p.\n", iface);
631 
635 
636  return ret;
637 }
638 
639 static HRESULT WINAPI d3d9_device_EvictManagedResources(IDirect3DDevice9Ex *iface)
640 {
642 
643  TRACE("iface %p.\n", iface);
644 
648 
649  return D3D_OK;
650 }
651 
652 static HRESULT WINAPI d3d9_device_GetDirect3D(IDirect3DDevice9Ex *iface, IDirect3D9 **d3d9)
653 {
655 
656  TRACE("iface %p, d3d9 %p.\n", iface, d3d9);
657 
658  if (!d3d9)
659  return D3DERR_INVALIDCALL;
660 
661  return IDirect3D9Ex_QueryInterface(&device->d3d_parent->IDirect3D9Ex_iface, &IID_IDirect3D9, (void **)d3d9);
662 }
663 
664 static HRESULT WINAPI d3d9_device_GetDeviceCaps(IDirect3DDevice9Ex *iface, D3DCAPS9 *caps)
665 {
667  WINED3DCAPS wined3d_caps;
668  HRESULT hr;
669 
670  TRACE("iface %p, caps %p.\n", iface, caps);
671 
672  if (!caps)
673  return D3DERR_INVALIDCALL;
674 
675  memset(caps, 0, sizeof(*caps));
676 
678  hr = wined3d_device_get_device_caps(device->wined3d_device, &wined3d_caps);
680 
681  d3dcaps_from_wined3dcaps(caps, &wined3d_caps);
682 
683  return hr;
684 }
685 
686 static HRESULT WINAPI d3d9_device_GetDisplayMode(IDirect3DDevice9Ex *iface, UINT swapchain, D3DDISPLAYMODE *mode)
687 {
689  struct wined3d_display_mode wined3d_mode;
690  HRESULT hr;
691 
692  TRACE("iface %p, swapchain %u, mode %p.\n", iface, swapchain, mode);
693 
695  hr = wined3d_device_get_display_mode(device->wined3d_device, swapchain, &wined3d_mode, NULL);
697 
698  if (SUCCEEDED(hr))
699  {
700  mode->Width = wined3d_mode.width;
701  mode->Height = wined3d_mode.height;
702  mode->RefreshRate = wined3d_mode.refresh_rate;
703  mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
704  }
705 
706  return hr;
707 }
708 
709 static HRESULT WINAPI d3d9_device_GetCreationParameters(IDirect3DDevice9Ex *iface,
710  D3DDEVICE_CREATION_PARAMETERS *parameters)
711 {
713 
714  TRACE("iface %p, parameters %p.\n", iface, parameters);
715 
718  (struct wined3d_device_creation_parameters *)parameters);
720 
721  return D3D_OK;
722 }
723 
724 static HRESULT WINAPI d3d9_device_SetCursorProperties(IDirect3DDevice9Ex *iface,
725  UINT hotspot_x, UINT hotspot_y, IDirect3DSurface9 *bitmap)
726 {
729  HRESULT hr;
730 
731  TRACE("iface %p, hotspot_x %u, hotspot_y %u, bitmap %p.\n",
732  iface, hotspot_x, hotspot_y, bitmap);
733 
734  if (!bitmap)
735  {
736  WARN("No cursor bitmap, returning D3DERR_INVALIDCALL.\n");
737  return D3DERR_INVALIDCALL;
738  }
739 
742  hotspot_x, hotspot_y, bitmap_impl->wined3d_texture, bitmap_impl->sub_resource_idx);
744 
745  return hr;
746 }
747 
748 static void WINAPI d3d9_device_SetCursorPosition(IDirect3DDevice9Ex *iface, int x, int y, DWORD flags)
749 {
751 
752  TRACE("iface %p, x %u, y %u, flags %#x.\n", iface, x, y, flags);
753 
755  wined3d_device_set_cursor_position(device->wined3d_device, x, y, flags);
757 }
758 
759 static BOOL WINAPI d3d9_device_ShowCursor(IDirect3DDevice9Ex *iface, BOOL show)
760 {
762  BOOL ret;
763 
764  TRACE("iface %p, show %#x.\n", iface, show);
765 
767  ret = wined3d_device_show_cursor(device->wined3d_device, show);
769 
770  return ret;
771 }
772 
774  D3DPRESENT_PARAMETERS *present_parameters, IDirect3DSwapChain9 **swapchain)
775 {
778  struct d3d9_swapchain *object;
779  unsigned int swap_interval;
780  unsigned int i, count;
781  HRESULT hr;
782 
783  TRACE("iface %p, present_parameters %p, swapchain %p.\n",
784  iface, present_parameters, swapchain);
785 
786  if (!present_parameters->Windowed)
787  {
788  WARN("Trying to create an additional fullscreen swapchain, returning D3DERR_INVALIDCALL.\n");
789  return D3DERR_INVALIDCALL;
790  }
791 
794  for (i = 0; i < count; ++i)
795  {
797 
800 
801  if (!desc.windowed)
802  {
804  WARN("Trying to create an additional swapchain in fullscreen mode, returning D3DERR_INVALIDCALL.\n");
805  return D3DERR_INVALIDCALL;
806  }
807  }
809 
810  if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters,
811  device->d3d_parent->extended))
812  return D3DERR_INVALIDCALL;
815  *swapchain = (IDirect3DSwapChain9 *)&object->IDirect3DSwapChain9Ex_iface;
817  &desc, present_parameters->PresentationInterval);
818 
819  return hr;
820 }
821 
822 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_GetSwapChain(IDirect3DDevice9Ex *iface,
823  UINT swapchain_idx, IDirect3DSwapChain9 **swapchain)
824 {
826  HRESULT hr;
827 
828  TRACE("iface %p, swapchain_idx %u, swapchain %p.\n", iface, swapchain_idx, swapchain);
829 
831  if (swapchain_idx < device->implicit_swapchain_count)
832  {
833  *swapchain = (IDirect3DSwapChain9 *)&device->implicit_swapchains[swapchain_idx]->IDirect3DSwapChain9Ex_iface;
834  IDirect3DSwapChain9Ex_AddRef(*swapchain);
835  hr = D3D_OK;
836  }
837  else
838  {
839  *swapchain = NULL;
841  }
843 
844  return hr;
845 }
846 
847 static UINT WINAPI d3d9_device_GetNumberOfSwapChains(IDirect3DDevice9Ex *iface)
848 {
850  UINT count;
851 
852  TRACE("iface %p.\n", iface);
853 
857 
858  return count;
859 }
860 
862 {
864  IDirect3DBaseTexture9 *texture;
865  struct d3d9_surface *surface;
866  IUnknown *parent;
867 
869  if (desc.access & WINED3D_RESOURCE_ACCESS_CPU)
870  return D3D_OK;
871 
872  if (desc.resource_type != WINED3D_RTYPE_TEXTURE_2D)
873  {
874  WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource);
875  return D3DERR_INVALIDCALL;
876  }
877 
879  if (parent && SUCCEEDED(IUnknown_QueryInterface(parent, &IID_IDirect3DBaseTexture9, (void **)&texture)))
880  {
882  WARN("Texture %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", texture, resource);
883  return D3DERR_INVALIDCALL;
884  }
885 
887  if (!surface->resource.refcount)
888  return D3D_OK;
889 
890  WARN("Surface %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", surface);
891  return D3DERR_INVALIDCALL;
892 }
893 
895 {
896  UINT i, new_swapchain_count = wined3d_device_get_swapchain_count(device->wined3d_device);
898 
899  if (!(device->implicit_swapchains = heap_alloc(new_swapchain_count * sizeof(*device->implicit_swapchains))))
900  return E_OUTOFMEMORY;
901 
902  for (i = 0; i < new_swapchain_count; ++i)
903  {
905  device->implicit_swapchains[i] = wined3d_swapchain_get_parent(wined3d_swapchain);
906  }
907  device->implicit_swapchain_count = new_swapchain_count;
908 
909  return D3D_OK;
910 }
911 
913  D3DPRESENT_PARAMETERS *present_parameters, D3DDISPLAYMODEEX *mode)
914 {
915  BOOL extended = device->d3d_parent->extended;
916  struct wined3d_swapchain_desc swapchain_desc;
917  struct wined3d_display_mode wined3d_mode;
918  struct wined3d_rendertarget_view *rtv;
919  unsigned int i;
920  HRESULT hr;
921 
922  if (!extended && device->device_state == D3D9_DEVICE_STATE_LOST)
923  {
924  WARN("App not active, returning D3DERR_DEVICELOST.\n");
925  return D3DERR_DEVICELOST;
926  }
927 
928  if (mode)
929  {
930  wined3d_mode.width = mode->Width;
931  wined3d_mode.height = mode->Height;
932  wined3d_mode.refresh_rate = mode->RefreshRate;
933  wined3d_mode.format_id = wined3dformat_from_d3dformat(mode->Format);
934  wined3d_mode.scanline_ordering = mode->ScanLineOrdering;
935  }
936 
937  if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters, extended))
938  return D3DERR_INVALIDCALL;
939 
941 
942  if (device->vertex_buffer)
943  {
944  wined3d_buffer_decref(device->vertex_buffer);
945  device->vertex_buffer = NULL;
946  device->vertex_buffer_size = 0;
947  }
948 
949  if (device->index_buffer)
950  {
951  wined3d_buffer_decref(device->index_buffer);
952  device->index_buffer = NULL;
953  device->index_buffer_size = 0;
954  }
955 
956  if (SUCCEEDED(hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc,
957  mode ? &wined3d_mode : NULL, reset_enum_callback, !extended)))
958  {
959  heap_free(device->implicit_swapchains);
960 
961  if (!extended)
962  {
964  !!swapchain_desc.enable_auto_depth_stencil);
965  }
966 
968  {
969  device->device_state = D3D9_DEVICE_STATE_NOT_RESET;
970  }
971  else
972  {
973  device->implicit_swapchains[0]->swap_interval
974  = wined3dswapinterval_from_d3d(present_parameters->PresentationInterval);
975  wined3d_swapchain_get_desc(device->implicit_swapchains[0]->wined3d_swapchain, &swapchain_desc);
976  present_parameters->BackBufferWidth = swapchain_desc.backbuffer_width;
977  present_parameters->BackBufferHeight = swapchain_desc.backbuffer_height;
978  present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc.backbuffer_format);
979  present_parameters->BackBufferCount = swapchain_desc.backbuffer_count;
980 
981  device->device_state = D3D9_DEVICE_STATE_OK;
982  }
983 
984  rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0);
986  for (i = 1; i < ARRAY_SIZE(device->render_targets); ++i)
987  device->render_targets[i] = NULL;
988  }
989  else if (!extended)
990  {
991  device->device_state = D3D9_DEVICE_STATE_NOT_RESET;
992  }
993 
995 
996  return hr;
997 }
998 
999 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Reset(IDirect3DDevice9Ex *iface,
1000  D3DPRESENT_PARAMETERS *present_parameters)
1001 {
1003 
1004  TRACE("iface %p, present_parameters %p.\n", iface, present_parameters);
1005 
1006  return d3d9_device_reset(device, present_parameters, NULL);
1007 }
1008 
1009 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex *iface,
1010  const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region)
1011 {
1013  struct d3d9_swapchain *swapchain;
1014  unsigned int i;
1015  HRESULT hr;
1016 
1017  TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p.\n",
1018  iface, src_rect, dst_rect, dst_window_override, dirty_region);
1019 
1020  if (device->device_state != D3D9_DEVICE_STATE_OK)
1021  return device->d3d_parent->extended ? S_PRESENT_OCCLUDED : D3DERR_DEVICELOST;
1022 
1023  if (dirty_region)
1024  FIXME("Ignoring dirty_region %p.\n", dirty_region);
1025 
1027  for (i = 0; i < device->implicit_swapchain_count; ++i)
1028  {
1029  swapchain = device->implicit_swapchains[i];
1031  src_rect, dst_rect, dst_window_override, swapchain->swap_interval, 0)))
1032  {
1034  return hr;
1035  }
1036  }
1038 
1039  return D3D_OK;
1040 }
1041 
1042 static HRESULT WINAPI d3d9_device_GetBackBuffer(IDirect3DDevice9Ex *iface, UINT swapchain,
1043  UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface9 **backbuffer)
1044 {
1046  HRESULT hr;
1047 
1048  TRACE("iface %p, swapchain %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
1049  iface, swapchain, backbuffer_idx, backbuffer_type, backbuffer);
1050 
1051  /* backbuffer_type is ignored by native. */
1052 
1053  /* No need to check for backbuffer == NULL, Windows crashes in that case. */
1054  *backbuffer = NULL;
1055 
1057  if (swapchain >= device->implicit_swapchain_count)
1058  {
1060  WARN("Swapchain index %u is out of range, returning D3DERR_INVALIDCALL.\n", swapchain);
1061  return D3DERR_INVALIDCALL;
1062  }
1063 
1064  hr = IDirect3DSwapChain9Ex_GetBackBuffer(&device->implicit_swapchains[swapchain]->IDirect3DSwapChain9Ex_iface,
1065  backbuffer_idx, backbuffer_type, backbuffer);
1067 
1068  return hr;
1069 }
1070 
1071 static HRESULT WINAPI d3d9_device_GetRasterStatus(IDirect3DDevice9Ex *iface,
1072  UINT swapchain, D3DRASTER_STATUS *raster_status)
1073 {
1075  HRESULT hr;
1076 
1077  TRACE("iface %p, swapchain %u, raster_status %p.\n", iface, swapchain, raster_status);
1078 
1080  hr = wined3d_device_get_raster_status(device->wined3d_device,
1081  swapchain, (struct wined3d_raster_status *)raster_status);
1083 
1084  return hr;
1085 }
1086 
1087 static HRESULT WINAPI d3d9_device_SetDialogBoxMode(IDirect3DDevice9Ex *iface, BOOL enable)
1088 {
1090  HRESULT hr;
1091 
1092  TRACE("iface %p, enable %#x.\n", iface, enable);
1093 
1095  hr = wined3d_device_set_dialog_box_mode(device->wined3d_device, enable);
1097 
1098  return hr;
1099 }
1100 
1101 static void WINAPI d3d9_device_SetGammaRamp(IDirect3DDevice9Ex *iface,
1102  UINT swapchain, DWORD flags, const D3DGAMMARAMP *ramp)
1103 {
1105 
1106  TRACE("iface %p, swapchain %u, flags %#x, ramp %p.\n", iface, swapchain, flags, ramp);
1107 
1108  /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
1110  wined3d_device_set_gamma_ramp(device->wined3d_device, swapchain, flags, (const struct wined3d_gamma_ramp *)ramp);
1112 }
1113 
1114 static void WINAPI d3d9_device_GetGammaRamp(IDirect3DDevice9Ex *iface, UINT swapchain, D3DGAMMARAMP *ramp)
1115 {
1117 
1118  TRACE("iface %p, swapchain %u, ramp %p.\n", iface, swapchain, ramp);
1119 
1120  /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
1122  wined3d_device_get_gamma_ramp(device->wined3d_device, swapchain, (struct wined3d_gamma_ramp *)ramp);
1124 }
1125 
1126 static HRESULT WINAPI d3d9_device_CreateTexture(IDirect3DDevice9Ex *iface,
1128  D3DPOOL pool, IDirect3DTexture9 **texture, HANDLE *shared_handle)
1129 {
1131  struct d3d9_texture *object;
1132  BOOL set_mem = FALSE;
1133  HRESULT hr;
1134 
1135  TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
1136  iface, width, height, levels, usage, format, pool, texture, shared_handle);
1137 
1138  *texture = NULL;
1139  if (shared_handle)
1140  {
1141  if (!device->d3d_parent->extended)
1142  {
1143  WARN("Trying to create a shared or user memory texture on a non-ex device.\n");
1144  return E_NOTIMPL;
1145  }
1146 
1147  if (pool == D3DPOOL_SYSTEMMEM)
1148  {
1149  if (levels != 1)
1150  return D3DERR_INVALIDCALL;
1151  set_mem = TRUE;
1152  }
1153  else
1154  {
1155  if (pool != D3DPOOL_DEFAULT)
1156  {
1157  WARN("Trying to create a shared texture in pool %#x.\n", pool);
1158  return D3DERR_INVALIDCALL;
1159  }
1160  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1161  }
1162  }
1163 
1164  if (!(object = heap_alloc_zero(sizeof(*object))))
1165  return D3DERR_OUTOFVIDEOMEMORY;
1166 
1168  if (FAILED(hr))
1169  {
1170  WARN("Failed to initialize texture, hr %#x.\n", hr);
1171  heap_free(object);
1172  return hr;
1173  }
1174 
1175  if (set_mem)
1176  wined3d_texture_update_desc(object->wined3d_texture, width, height,
1178  *shared_handle, 0);
1179 
1180  TRACE("Created texture %p.\n", object);
1181  *texture = (IDirect3DTexture9 *)&object->IDirect3DBaseTexture9_iface;
1182 
1183  return D3D_OK;
1184 }
1185 
1186 static HRESULT WINAPI d3d9_device_CreateVolumeTexture(IDirect3DDevice9Ex *iface,
1188  D3DPOOL pool, IDirect3DVolumeTexture9 **texture, HANDLE *shared_handle)
1189 {
1191  struct d3d9_texture *object;
1192  HRESULT hr;
1193 
1194  TRACE("iface %p, width %u, height %u, depth %u, levels %u, "
1195  "usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
1196  iface, width, height, depth, levels,
1197  usage, format, pool, texture, shared_handle);
1198 
1199  *texture = NULL;
1200  if (shared_handle)
1201  {
1202  if (!device->d3d_parent->extended)
1203  {
1204  WARN("Trying to create a shared volume texture on a non-ex device.\n");
1205  return E_NOTIMPL;
1206  }
1207 
1208  if (pool != D3DPOOL_DEFAULT)
1209  {
1210  WARN("Trying to create a shared volume texture in pool %#x.\n", pool);
1211  return D3DERR_INVALIDCALL;
1212  }
1213  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1214  }
1215 
1216  if (!(object = heap_alloc_zero(sizeof(*object))))
1217  return D3DERR_OUTOFVIDEOMEMORY;
1218 
1220  if (FAILED(hr))
1221  {
1222  WARN("Failed to initialize volume texture, hr %#x.\n", hr);
1223  heap_free(object);
1224  return hr;
1225  }
1226 
1227  TRACE("Created volume texture %p.\n", object);
1228  *texture = (IDirect3DVolumeTexture9 *)&object->IDirect3DBaseTexture9_iface;
1229 
1230  return D3D_OK;
1231 }
1232 
1233 static HRESULT WINAPI d3d9_device_CreateCubeTexture(IDirect3DDevice9Ex *iface,
1235  IDirect3DCubeTexture9 **texture, HANDLE *shared_handle)
1236 {
1238  struct d3d9_texture *object;
1239  HRESULT hr;
1240 
1241  TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
1242  iface, edge_length, levels, usage, format, pool, texture, shared_handle);
1243 
1244  *texture = NULL;
1245  if (shared_handle)
1246  {
1247  if (!device->d3d_parent->extended)
1248  {
1249  WARN("Trying to create a shared cube texture on a non-ex device.\n");
1250  return E_NOTIMPL;
1251  }
1252 
1253  if (pool != D3DPOOL_DEFAULT)
1254  {
1255  WARN("Trying to create a shared cube texture in pool %#x.\n", pool);
1256  return D3DERR_INVALIDCALL;
1257  }
1258  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1259  }
1260 
1261  if (!(object = heap_alloc_zero(sizeof(*object))))
1262  return D3DERR_OUTOFVIDEOMEMORY;
1263 
1264  hr = cubetexture_init(object, device, edge_length, levels, usage, format, pool);
1265  if (FAILED(hr))
1266  {
1267  WARN("Failed to initialize cube texture, hr %#x.\n", hr);
1268  heap_free(object);
1269  return hr;
1270  }
1271 
1272  TRACE("Created cube texture %p.\n", object);
1273  *texture = (IDirect3DCubeTexture9 *)&object->IDirect3DBaseTexture9_iface;
1274 
1275  return D3D_OK;
1276 }
1277 
1278 static HRESULT WINAPI d3d9_device_CreateVertexBuffer(IDirect3DDevice9Ex *iface, UINT size,
1279  DWORD usage, DWORD fvf, D3DPOOL pool, IDirect3DVertexBuffer9 **buffer,
1280  HANDLE *shared_handle)
1281 {
1283  struct d3d9_vertexbuffer *object;
1284  HRESULT hr;
1285 
1286  TRACE("iface %p, size %u, usage %#x, fvf %#x, pool %#x, buffer %p, shared_handle %p.\n",
1287  iface, size, usage, fvf, pool, buffer, shared_handle);
1288 
1289  if (shared_handle)
1290  {
1291  if (!device->d3d_parent->extended)
1292  {
1293  WARN("Trying to create a shared vertex buffer on a non-ex device.\n");
1294  return E_NOTIMPL;
1295  }
1296 
1297  if (pool != D3DPOOL_DEFAULT)
1298  {
1299  WARN("Trying to create a shared vertex buffer in pool %#x.\n", pool);
1300  return D3DERR_NOTAVAILABLE;
1301  }
1302  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1303  }
1304 
1305  if (!(object = heap_alloc_zero(sizeof(*object))))
1306  return D3DERR_OUTOFVIDEOMEMORY;
1307 
1308  hr = vertexbuffer_init(object, device, size, usage, fvf, pool);
1309  if (FAILED(hr))
1310  {
1311  WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
1312  heap_free(object);
1313  return hr;
1314  }
1315 
1316  TRACE("Created vertex buffer %p.\n", object);
1317  *buffer = &object->IDirect3DVertexBuffer9_iface;
1318 
1319  return D3D_OK;
1320 }
1321 
1322 static HRESULT WINAPI d3d9_device_CreateIndexBuffer(IDirect3DDevice9Ex *iface, UINT size,
1323  DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer9 **buffer,
1324  HANDLE *shared_handle)
1325 {
1327  struct d3d9_indexbuffer *object;
1328  HRESULT hr;
1329 
1330  TRACE("iface %p, size %u, usage %#x, format %#x, pool %#x, buffer %p, shared_handle %p.\n",
1331  iface, size, usage, format, pool, buffer, shared_handle);
1332 
1333  if (shared_handle)
1334  {
1335  if (!device->d3d_parent->extended)
1336  {
1337  WARN("Trying to create a shared index buffer on a non-ex device.\n");
1338  return E_NOTIMPL;
1339  }
1340 
1341  if (pool != D3DPOOL_DEFAULT)
1342  {
1343  WARN("Trying to create a shared index buffer in pool %#x.\n", pool);
1344  return D3DERR_NOTAVAILABLE;
1345  }
1346  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1347  }
1348 
1349  if (!(object = heap_alloc_zero(sizeof(*object))))
1350  return D3DERR_OUTOFVIDEOMEMORY;
1351 
1352  hr = indexbuffer_init(object, device, size, usage, format, pool);
1353  if (FAILED(hr))
1354  {
1355  WARN("Failed to initialize index buffer, hr %#x.\n", hr);
1356  heap_free(object);
1357  return hr;
1358  }
1359 
1360  TRACE("Created index buffer %p.\n", object);
1361  *buffer = &object->IDirect3DIndexBuffer9_iface;
1362 
1363  return D3D_OK;
1364 }
1365 
1367  D3DFORMAT format, DWORD flags, IDirect3DSurface9 **surface, UINT usage, D3DPOOL pool,
1368  D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, void *user_mem)
1369 {
1370  struct wined3d_resource_desc desc;
1371  struct d3d9_surface *surface_impl;
1372  struct wined3d_texture *texture;
1373  HRESULT hr;
1374 
1375  TRACE("device %p, width %u, height %u, format %#x, flags %#x, surface %p.\n"
1376  "usage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n",
1377  device, width, height, format, flags, surface, usage, pool,
1378  multisample_type, multisample_quality);
1379 
1380  desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
1382  desc.multisample_type = multisample_type;
1383  desc.multisample_quality = multisample_quality;
1384  desc.usage = usage & WINED3DUSAGE_MASK;
1385  if (pool == D3DPOOL_SCRATCH)
1386  desc.usage |= WINED3DUSAGE_SCRATCH;
1389  desc.width = width;
1390  desc.height = height;
1391  desc.depth = 1;
1392  desc.size = 0;
1393 
1394  if (is_gdi_compat_wined3dformat(desc.format))
1396 
1398 
1399  if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &desc,
1401  {
1403  WARN("Failed to create texture, hr %#x.\n", hr);
1404  if (hr == WINED3DERR_NOTAVAILABLE)
1406  return hr;
1407  }
1408 
1410  surface_impl->parent_device = &device->IDirect3DDevice9Ex_iface;
1411  *surface = &surface_impl->IDirect3DSurface9_iface;
1412  IDirect3DSurface9_AddRef(*surface);
1413 
1414  if (user_mem)
1416  desc.format, multisample_type, multisample_quality, user_mem, 0);
1417 
1419 
1421 
1422  return D3D_OK;
1423 }
1424 
1426 {
1427  switch (format)
1428  {
1435  return TRUE;
1436  default:
1437  return FALSE;
1438  }
1439 }
1440 
1442  D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
1443  BOOL lockable, IDirect3DSurface9 **surface, HANDLE *shared_handle)
1444 {
1446  DWORD flags = 0;
1447 
1448  TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
1449  "lockable %#x, surface %p, shared_handle %p.\n",
1450  iface, width, height, format, multisample_type, multisample_quality,
1451  lockable, surface, shared_handle);
1452 
1453  *surface = NULL;
1454  if (shared_handle)
1455  {
1456  if (!device->d3d_parent->extended)
1457  {
1458  WARN("Trying to create a shared render target on a non-ex device.\n");
1459  return E_NOTIMPL;
1460  }
1461 
1462  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1463  }
1464 
1465  if (lockable)
1467 
1469  D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL);
1470 }
1471 
1473  D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
1474  BOOL discard, IDirect3DSurface9 **surface, HANDLE *shared_handle)
1475 {
1478 
1479  TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
1480  "discard %#x, surface %p, shared_handle %p.\n",
1481  iface, width, height, format, multisample_type, multisample_quality,
1482  discard, surface, shared_handle);
1483 
1484  *surface = NULL;
1485  if (shared_handle)
1486  {
1487  if (!device->d3d_parent->extended)
1488  {
1489  WARN("Trying to create a shared depth stencil on a non-ex device.\n");
1490  return E_NOTIMPL;
1491  }
1492 
1493  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1494  }
1495 
1496  if (discard)
1498 
1500  D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL);
1501 }
1502 
1503 
1504 static HRESULT WINAPI d3d9_device_UpdateSurface(IDirect3DDevice9Ex *iface,
1505  IDirect3DSurface9 *src_surface, const RECT *src_rect,
1506  IDirect3DSurface9 *dst_surface, const POINT *dst_point)
1507 {
1509  struct d3d9_surface *src = unsafe_impl_from_IDirect3DSurface9(src_surface);
1510  struct d3d9_surface *dst = unsafe_impl_from_IDirect3DSurface9(dst_surface);
1511  struct wined3d_sub_resource_desc src_desc, dst_desc;
1512  struct wined3d_box src_box;
1513  HRESULT hr;
1514 
1515  TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_point %p.\n",
1516  iface, src_surface, src_rect, dst_surface, dst_point);
1517 
1519 
1520  wined3d_texture_get_sub_resource_desc(src->wined3d_texture, src->sub_resource_idx, &src_desc);
1521  wined3d_texture_get_sub_resource_desc(dst->wined3d_texture, dst->sub_resource_idx, &dst_desc);
1522  if (src_desc.format != dst_desc.format)
1523  {
1525  WARN("Surface formats (%#x/%#x) don't match.\n",
1528  return D3DERR_INVALIDCALL;
1529  }
1530 
1531  if (src_rect)
1532  wined3d_box_set(&src_box, src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1);
1533  else
1534  wined3d_box_set(&src_box, 0, 0, src_desc.width, src_desc.height, 0, 1);
1535 
1537  wined3d_texture_get_resource(dst->wined3d_texture), dst->sub_resource_idx, dst_point ? dst_point->x : 0,
1538  dst_point ? dst_point->y : 0, 0, wined3d_texture_get_resource(src->wined3d_texture),
1539  src->sub_resource_idx, &src_box, 0);
1540  if (SUCCEEDED(hr) && dst->texture)
1542 
1544 
1545  if (FAILED(hr))
1546  return D3DERR_INVALIDCALL;
1547 
1548  return hr;
1549 }
1550 
1551 static HRESULT WINAPI d3d9_device_UpdateTexture(IDirect3DDevice9Ex *iface,
1552  IDirect3DBaseTexture9 *src_texture, IDirect3DBaseTexture9 *dst_texture)
1553 {
1555  struct d3d9_texture *src_impl, *dst_impl;
1556  HRESULT hr;
1557 
1558  TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
1559 
1560  src_impl = unsafe_impl_from_IDirect3DBaseTexture9(src_texture);
1561  dst_impl = unsafe_impl_from_IDirect3DBaseTexture9(dst_texture);
1562 
1564  hr = wined3d_device_update_texture(device->wined3d_device,
1565  src_impl->wined3d_texture, dst_impl->wined3d_texture);
1566  if (SUCCEEDED(hr))
1569 
1570  return hr;
1571 }
1572 
1573 static HRESULT WINAPI d3d9_device_GetRenderTargetData(IDirect3DDevice9Ex *iface,
1574  IDirect3DSurface9 *render_target, IDirect3DSurface9 *dst_surface)
1575 {
1576  struct d3d9_surface *rt_impl = unsafe_impl_from_IDirect3DSurface9(render_target);
1577  struct d3d9_surface *dst_impl = unsafe_impl_from_IDirect3DSurface9(dst_surface);
1578  struct wined3d_sub_resource_desc wined3d_desc;
1579  RECT dst_rect, src_rect;
1580  HRESULT hr;
1581 
1582  TRACE("iface %p, render_target %p, dst_surface %p.\n", iface, render_target, dst_surface);
1583 
1584  if (!render_target || !dst_surface)
1585  return D3DERR_INVALIDCALL;
1586 
1588  wined3d_texture_get_sub_resource_desc(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &wined3d_desc);
1589  SetRect(&dst_rect, 0, 0, wined3d_desc.width, wined3d_desc.height);
1590 
1591  wined3d_texture_get_sub_resource_desc(rt_impl->wined3d_texture, rt_impl->sub_resource_idx, &wined3d_desc);
1592  SetRect(&src_rect, 0, 0, wined3d_desc.width, wined3d_desc.height);
1593 
1594  /* TODO: Check surface sizes, pools, etc. */
1595  if (wined3d_desc.multisample_type)
1597  else
1598  hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect,
1599  rt_impl->wined3d_texture, rt_impl->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT);
1601 
1602  return hr;
1603 }
1604 
1605 static HRESULT WINAPI d3d9_device_GetFrontBufferData(IDirect3DDevice9Ex *iface,
1606  UINT swapchain, IDirect3DSurface9 *dst_surface)
1607 {
1609  struct d3d9_surface *dst_impl = unsafe_impl_from_IDirect3DSurface9(dst_surface);
1611 
1612  TRACE("iface %p, swapchain %u, dst_surface %p.\n", iface, swapchain, dst_surface);
1613 
1615  if (swapchain < device->implicit_swapchain_count)
1616  hr = wined3d_swapchain_get_front_buffer_data(device->implicit_swapchains[swapchain]->wined3d_swapchain,
1617  dst_impl->wined3d_texture, dst_impl->sub_resource_idx);
1619 
1620  return hr;
1621 }
1622 
1623 static HRESULT WINAPI d3d9_device_StretchRect(IDirect3DDevice9Ex *iface, IDirect3DSurface9 *src_surface,
1624  const RECT *src_rect, IDirect3DSurface9 *dst_surface, const RECT *dst_rect, D3DTEXTUREFILTERTYPE filter)
1625 {
1627  struct d3d9_surface *src = unsafe_impl_from_IDirect3DSurface9(src_surface);
1628  struct d3d9_surface *dst = unsafe_impl_from_IDirect3DSurface9(dst_surface);
1629  struct wined3d_sub_resource_desc src_desc, dst_desc;
1631  RECT d, s;
1632 
1633  TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %#x.\n",
1634  iface, src_surface, src_rect, dst_surface, dst_rect, filter);
1635 
1637  wined3d_texture_get_sub_resource_desc(dst->wined3d_texture, dst->sub_resource_idx, &dst_desc);
1638  if (!dst_rect)
1639  {
1640  SetRect(&d, 0, 0, dst_desc.width, dst_desc.height);
1641  dst_rect = &d;
1642  }
1643 
1644  wined3d_texture_get_sub_resource_desc(src->wined3d_texture, src->sub_resource_idx, &src_desc);
1645  if (!src_rect)
1646  {
1647  SetRect(&s, 0, 0, src_desc.width, src_desc.height);
1648  src_rect = &s;
1649  }
1650 
1651  if (dst_desc.access & WINED3D_RESOURCE_ACCESS_CPU)
1652  {
1653  WARN("Destination resource is not in DEFAULT pool.\n");
1654  goto done;
1655  }
1656  if (src_desc.access & WINED3D_RESOURCE_ACCESS_CPU)
1657  {
1658  WARN("Source resource is not in DEFAULT pool.\n");
1659  goto done;
1660  }
1661 
1662  if (dst->texture && !(dst_desc.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL)))
1663  {
1664  WARN("Destination is a regular texture.\n");
1665  goto done;
1666  }
1667 
1668  if (src_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
1669  {
1670  if (device->in_scene)
1671  {
1672  WARN("Rejecting depth / stencil blit while in scene.\n");
1673  goto done;
1674  }
1675 
1676  if (src_rect->left || src_rect->top || src_rect->right != src_desc.width
1677  || src_rect->bottom != src_desc.height)
1678  {
1679  WARN("Rejecting depth / stencil blit with invalid source rect %s.\n",
1680  wine_dbgstr_rect(src_rect));
1681  goto done;
1682  }
1683 
1684  if (dst_rect->left || dst_rect->top || dst_rect->right != dst_desc.width
1685  || dst_rect->bottom != dst_desc.height)
1686  {
1687  WARN("Rejecting depth / stencil blit with invalid destination rect %s.\n",
1688  wine_dbgstr_rect(dst_rect));
1689  goto done;
1690  }
1691 
1692  if (src_desc.width != dst_desc.width || src_desc.height != dst_desc.height)
1693  {
1694  WARN("Rejecting depth / stencil blit with mismatched surface sizes.\n");
1695  goto done;
1696  }
1697  }
1698 
1699  hr = wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, dst_rect,
1700  src->wined3d_texture, src->sub_resource_idx, src_rect, 0, NULL, filter);
1701  if (hr == WINEDDERR_INVALIDRECT)
1703  if (SUCCEEDED(hr) && dst->texture)
1705 
1706 done:
1708  return hr;
1709 }
1710 
1711 static HRESULT WINAPI d3d9_device_ColorFill(IDirect3DDevice9Ex *iface,
1712  IDirect3DSurface9 *surface, const RECT *rect, D3DCOLOR color)
1713 {
1714  const struct wined3d_color c =
1715  {
1716  ((color >> 16) & 0xff) / 255.0f,
1717  ((color >> 8) & 0xff) / 255.0f,
1718  (color & 0xff) / 255.0f,
1719  ((color >> 24) & 0xff) / 255.0f,
1720  };
1722  struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface);
1724  struct wined3d_rendertarget_view *rtv;
1725  HRESULT hr;
1726 
1727  TRACE("iface %p, surface %p, rect %p, color 0x%08x.\n", iface, surface, rect, color);
1728 
1730 
1732  surface_impl->sub_resource_idx, &desc)))
1733  {
1735  return D3DERR_INVALIDCALL;
1736  }
1737 
1738  if (desc.access & WINED3D_RESOURCE_ACCESS_CPU)
1739  {
1741  WARN("Colour fills are not allowed on surfaces with resource access %#x.\n", desc.access);
1742  return D3DERR_INVALIDCALL;
1743  }
1745  {
1747  WARN("Colorfill is not allowed on non-RT textures, returning D3DERR_INVALIDCALL.\n");
1748  return D3DERR_INVALIDCALL;
1749  }
1750  if (desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
1751  {
1753  WARN("Colorfill is not allowed on depth stencil surfaces, returning D3DERR_INVALIDCALL.\n");
1754  return D3DERR_INVALIDCALL;
1755  }
1756 
1757  rtv = d3d9_surface_acquire_rendertarget_view(surface_impl);
1759  rtv, rect, WINED3DCLEAR_TARGET, &c, 0.0f, 0);
1760  d3d9_surface_release_rendertarget_view(surface_impl, rtv);
1761  if (SUCCEEDED(hr) && surface_impl->texture)
1763 
1765 
1766  return hr;
1767 }
1768 
1769 static HRESULT WINAPI d3d9_device_CreateOffscreenPlainSurface(IDirect3DDevice9Ex *iface,
1770  UINT width, UINT height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface,
1771  HANDLE *shared_handle)
1772 {
1774  void *user_mem = NULL;
1775 
1776  TRACE("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p.\n",
1777  iface, width, height, format, pool, surface, shared_handle);
1778 
1779  *surface = NULL;
1780  if (pool == D3DPOOL_MANAGED)
1781  {
1782  WARN("Attempting to create a managed offscreen plain surface.\n");
1783  return D3DERR_INVALIDCALL;
1784  }
1785 
1786  if (shared_handle)
1787  {
1788  if (!device->d3d_parent->extended)
1789  {
1790  WARN("Trying to create a shared or user memory surface on a non-ex device.\n");
1791  return E_NOTIMPL;
1792  }
1793 
1794  if (pool == D3DPOOL_SYSTEMMEM)
1795  user_mem = *shared_handle;
1796  else
1797  {
1798  if (pool != D3DPOOL_DEFAULT)
1799  {
1800  WARN("Trying to create a shared surface in pool %#x.\n", pool);
1801  return D3DERR_INVALIDCALL;
1802  }
1803  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1804  }
1805  }
1806 
1807  /* FIXME: Offscreen surfaces are supposed to be always lockable,
1808  * regardless of the pool they're created in. Should we set dynamic usage
1809  * here? */
1811  WINED3D_TEXTURE_CREATE_MAPPABLE, surface, 0, pool, D3DMULTISAMPLE_NONE, 0, user_mem);
1812 }
1813 
1814 static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 *surface)
1815 {
1817  struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface);
1818  struct wined3d_rendertarget_view *rtv;
1819  HRESULT hr;
1820 
1821  TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface);
1822 
1824  {
1825  WARN("Invalid index %u specified.\n", idx);
1826  return D3DERR_INVALIDCALL;
1827  }
1828 
1829  if (!idx && !surface_impl)
1830  {
1831  WARN("Trying to set render target 0 to NULL.\n");
1832  return D3DERR_INVALIDCALL;
1833  }
1834 
1835  if (surface_impl && d3d9_surface_get_device(surface_impl) != device)
1836  {
1837  WARN("Render target surface does not match device.\n");
1838  return D3DERR_INVALIDCALL;
1839  }
1840 
1842  rtv = surface_impl ? d3d9_surface_acquire_rendertarget_view(surface_impl) : NULL;
1843  hr = wined3d_device_set_rendertarget_view(device->wined3d_device, idx, rtv, TRUE);
1844  d3d9_surface_release_rendertarget_view(surface_impl, rtv);
1845  if (SUCCEEDED(hr))
1846  device->render_targets[idx] = surface_impl;
1848 
1849  return hr;
1850 }
1851 
1852 static HRESULT WINAPI d3d9_device_GetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 **surface)
1853 {
1855  struct wined3d_rendertarget_view *wined3d_rtv;
1856  struct d3d9_surface *surface_impl;
1857  HRESULT hr = D3D_OK;
1858 
1859  TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface);
1860 
1861  if (!surface)
1862  return D3DERR_INVALIDCALL;
1863 
1865  {
1866  WARN("Invalid index %u specified.\n", idx);
1867  return D3DERR_INVALIDCALL;
1868  }
1869 
1871  if ((wined3d_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, idx)))
1872  {
1873  /* We want the sub resource parent here, since the view itself may be
1874  * internal to wined3d and may not have a parent. */
1876  *surface = &surface_impl->IDirect3DSurface9_iface;
1877  IDirect3DSurface9_AddRef(*surface);
1878  }
1879  else
1880  {
1881  hr = D3DERR_NOTFOUND;
1882  *surface = NULL;
1883  }
1885 
1886  return hr;
1887 }
1888 
1889 static HRESULT WINAPI d3d9_device_SetDepthStencilSurface(IDirect3DDevice9Ex *iface, IDirect3DSurface9 *depth_stencil)
1890 {
1892  struct d3d9_surface *ds_impl = unsafe_impl_from_IDirect3DSurface9(depth_stencil);
1893  struct wined3d_rendertarget_view *rtv;
1894 
1895  TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
1896 
1898  rtv = ds_impl ? d3d9_surface_acquire_rendertarget_view(ds_impl) : NULL;
1899  wined3d_device_set_depth_stencil_view(device->wined3d_device, rtv);
1902 
1903  return D3D_OK;
1904 }
1905 
1906 static HRESULT WINAPI d3d9_device_GetDepthStencilSurface(IDirect3DDevice9Ex *iface, IDirect3DSurface9 **depth_stencil)
1907 {
1909  struct wined3d_rendertarget_view *wined3d_dsv;
1910  struct d3d9_surface *surface_impl;
1911  HRESULT hr = D3D_OK;
1912 
1913  TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
1914 
1915  if (!depth_stencil)
1916  return D3DERR_INVALIDCALL;
1917 
1919  if ((wined3d_dsv = wined3d_device_get_depth_stencil_view(device->wined3d_device)))
1920  {
1921  /* We want the sub resource parent here, since the view itself may be
1922  * internal to wined3d and may not have a parent. */
1923  surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_dsv);
1924  *depth_stencil = &surface_impl->IDirect3DSurface9_iface;
1925  IDirect3DSurface9_AddRef(*depth_stencil);
1926  }
1927  else
1928  {
1929  hr = D3DERR_NOTFOUND;
1930  *depth_stencil = NULL;
1931  }
1933 
1934  return hr;
1935 }
1936 
1937 static HRESULT WINAPI d3d9_device_BeginScene(IDirect3DDevice9Ex *iface)
1938 {
1940  HRESULT hr;
1941 
1942  TRACE("iface %p.\n", iface);
1943 
1945  if (SUCCEEDED(hr = wined3d_device_begin_scene(device->wined3d_device)))
1946  device->in_scene = TRUE;
1948 
1949  return hr;
1950 }
1951 
1952 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_EndScene(IDirect3DDevice9Ex *iface)
1953 {
1955  HRESULT hr;
1956 
1957  TRACE("iface %p.\n", iface);
1958 
1960  if (SUCCEEDED(hr = wined3d_device_end_scene(device->wined3d_device)))
1961  device->in_scene = FALSE;
1963 
1964  return hr;
1965 }
1966 
1968 {
1969  unsigned int i;
1970 
1971  for (i = 0; i < ARRAY_SIZE(device->render_targets); ++i)
1972  {
1973  struct d3d9_surface *surface = device->render_targets[i];
1974 
1975  if (surface && surface->texture)
1977  }
1978 }
1979 
1980 static HRESULT WINAPI d3d9_device_Clear(IDirect3DDevice9Ex *iface, DWORD rect_count,
1981  const D3DRECT *rects, DWORD flags, D3DCOLOR color, float z, DWORD stencil)
1982 {
1983  const struct wined3d_color c =
1984  {
1985  ((color >> 16) & 0xff) / 255.0f,
1986  ((color >> 8) & 0xff) / 255.0f,
1987  (color & 0xff) / 255.0f,
1988  ((color >> 24) & 0xff) / 255.0f,
1989  };
1991  HRESULT hr;
1992 
1993  TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %u.\n",
1994  iface, rect_count, rects, flags, color, z, stencil);
1995 
1996  if (rect_count && !rects)
1997  {
1998  WARN("count %u with NULL rects.\n", rect_count);
1999  rect_count = 0;
2000  }
2001 
2003  hr = wined3d_device_clear(device->wined3d_device, rect_count, (const RECT *)rects, flags, &c, z, stencil);
2004  if (SUCCEEDED(hr))
2007 
2008  return hr;
2009 }
2010 
2011 static HRESULT WINAPI d3d9_device_SetTransform(IDirect3DDevice9Ex *iface,
2013 {
2015 
2016  TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
2017 
2018  /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
2020  wined3d_device_set_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
2022 
2023  return D3D_OK;
2024 }
2025 
2026 static HRESULT WINAPI d3d9_device_GetTransform(IDirect3DDevice9Ex *iface,
2028 {
2030 
2031  TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
2032 
2033  /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
2035  wined3d_device_get_transform(device->wined3d_device, state, (struct wined3d_matrix *)matrix);
2037 
2038  return D3D_OK;
2039 }
2040 
2041 static HRESULT WINAPI d3d9_device_MultiplyTransform(IDirect3DDevice9Ex *iface,
2043 {
2045 
2046  TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
2047 
2048  /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
2050  wined3d_device_multiply_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
2052 
2053  return D3D_OK;
2054 }
2055 
2056 static HRESULT WINAPI d3d9_device_SetViewport(IDirect3DDevice9Ex *iface, const D3DVIEWPORT9 *viewport)
2057 {
2059  struct wined3d_viewport vp;
2060 
2061  TRACE("iface %p, viewport %p.\n", iface, viewport);
2062 
2063  vp.x = viewport->X;
2064  vp.y = viewport->Y;
2065  vp.width = viewport->Width;
2066  vp.height = viewport->Height;
2067  vp.min_z = viewport->MinZ;
2068  vp.max_z = viewport->MaxZ;
2069 
2071  wined3d_device_set_viewports(device->wined3d_device, 1, &vp);
2073 
2074  return D3D_OK;
2075 }
2076 
2077 static HRESULT WINAPI d3d9_device_GetViewport(IDirect3DDevice9Ex *iface, D3DVIEWPORT9 *viewport)
2078 {
2081 
2082  TRACE("iface %p, viewport %p.\n", iface, viewport);
2083 
2087 
2088  viewport->X = wined3d_viewport.x;
2089  viewport->Y = wined3d_viewport.y;
2090  viewport->Width = wined3d_viewport.width;
2091  viewport->Height = wined3d_viewport.height;
2092  viewport->MinZ = wined3d_viewport.min_z;
2093  viewport->MaxZ = wined3d_viewport.max_z;
2094 
2095  return D3D_OK;
2096 }
2097 
2098 static HRESULT WINAPI d3d9_device_SetMaterial(IDirect3DDevice9Ex *iface, const D3DMATERIAL9 *material)
2099 {
2101 
2102  TRACE("iface %p, material %p.\n", iface, material);
2103 
2104  /* Note: D3DMATERIAL9 is compatible with struct wined3d_material. */
2106  wined3d_device_set_material(device->wined3d_device, (const struct wined3d_material *)material);
2108 
2109  return D3D_OK;
2110 }
2111 
2112 static HRESULT WINAPI d3d9_device_GetMaterial(IDirect3DDevice9Ex *iface, D3DMATERIAL9 *material)
2113 {
2115 
2116  TRACE("iface %p, material %p.\n", iface, material);
2117 
2118  /* Note: D3DMATERIAL9 is compatible with struct wined3d_material. */
2120  wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
2122 
2123  return D3D_OK;
2124 }
2125 
2126 static HRESULT WINAPI d3d9_device_SetLight(IDirect3DDevice9Ex *iface, DWORD index, const D3DLIGHT9 *light)
2127 {
2129  HRESULT hr;
2130 
2131  TRACE("iface %p, index %u, light %p.\n", iface, index, light);
2132 
2133  /* Note: D3DLIGHT9 is compatible with struct wined3d_light. */
2135  hr = wined3d_device_set_light(device->wined3d_device, index, (const struct wined3d_light *)light);
2137 
2138  return hr;
2139 }
2140 
2141 static HRESULT WINAPI d3d9_device_GetLight(IDirect3DDevice9Ex *iface, DWORD index, D3DLIGHT9 *light)
2142 {
2144  HRESULT hr;
2145 
2146  TRACE("iface %p, index %u, light %p.\n", iface, index, light);
2147 
2148  /* Note: D3DLIGHT9 is compatible with struct wined3d_light. */
2150  hr = wined3d_device_get_light(device->wined3d_device, index, (struct wined3d_light *)light);
2152 
2153  return hr;
2154 }
2155 
2156 static HRESULT WINAPI d3d9_device_LightEnable(IDirect3DDevice9Ex *iface, DWORD index, BOOL enable)
2157 {
2159  HRESULT hr;
2160 
2161  TRACE("iface %p, index %u, enable %#x.\n", iface, index, enable);
2162 
2164  hr = wined3d_device_set_light_enable(device->wined3d_device, index, enable);
2166 
2167  return hr;
2168 }
2169 
2170 static HRESULT WINAPI d3d9_device_GetLightEnable(IDirect3DDevice9Ex *iface, DWORD index, BOOL *enable)
2171 {
2173  HRESULT hr;
2174 
2175  TRACE("iface %p, index %u, enable %p.\n", iface, index, enable);
2176 
2178  hr = wined3d_device_get_light_enable(device->wined3d_device, index, enable);
2180 
2181  return hr;
2182 }
2183 
2184 static HRESULT WINAPI d3d9_device_SetClipPlane(IDirect3DDevice9Ex *iface, DWORD index, const float *plane)
2185 {
2187  HRESULT hr;
2188 
2189  TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
2190 
2191  index = min(index, device->max_user_clip_planes - 1);
2192 
2194  hr = wined3d_device_set_clip_plane(device->wined3d_device, index, (const struct wined3d_vec4 *)plane);
2196 
2197  return hr;
2198 }
2199 
2200 static HRESULT WINAPI d3d9_device_GetClipPlane(IDirect3DDevice9Ex *iface, DWORD index, float *plane)
2201 {
2203  HRESULT hr;
2204 
2205  TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
2206 
2207  index = min(index, device->max_user_clip_planes - 1);
2208 
2210  hr = wined3d_device_get_clip_plane(device->wined3d_device, index, (struct wined3d_vec4 *)plane);
2212 
2213  return hr;
2214 }
2215 
2218 {
2220 
2221  TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2222 
2226 
2227  return D3D_OK;
2228 }
2229 
2230 static HRESULT WINAPI d3d9_device_GetRenderState(IDirect3DDevice9Ex *iface,
2232 {
2234 
2235  TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2236 
2238  *value = wined3d_device_get_render_state(device->wined3d_device, state);
2240 
2241  return D3D_OK;
2242 }
2243 
2244 static HRESULT WINAPI d3d9_device_CreateStateBlock(IDirect3DDevice9Ex *iface,
2245  D3DSTATEBLOCKTYPE type, IDirect3DStateBlock9 **stateblock)
2246 {
2248  struct d3d9_stateblock *object;
2249  HRESULT hr;
2250 
2251  TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
2252 
2254  {
2255  WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL.\n");
2256  return D3DERR_INVALIDCALL;
2257  }
2258 
2259  if (!(object = heap_alloc_zero(sizeof(*object))))
2260  return E_OUTOFMEMORY;
2261 
2262  hr = stateblock_init(object, device, type, NULL);
2263  if (FAILED(hr))
2264  {
2265  WARN("Failed to initialize stateblock, hr %#x.\n", hr);
2266  heap_free(object);
2267  return hr;
2268  }
2269 
2270  TRACE("Created stateblock %p.\n", object);
2271  *stateblock = &object->IDirect3DStateBlock9_iface;
2272 
2273  return D3D_OK;
2274 }
2275 
2276 static HRESULT WINAPI d3d9_device_BeginStateBlock(IDirect3DDevice9Ex *iface)
2277 {
2279  HRESULT hr;
2280 
2281  TRACE("iface %p.\n", iface);
2282 
2284  hr = wined3d_device_begin_stateblock(device->wined3d_device);
2286 
2287  return hr;
2288 }
2289 
2290 static HRESULT WINAPI d3d9_device_EndStateBlock(IDirect3DDevice9Ex *iface, IDirect3DStateBlock9 **stateblock)
2291 {
2294  struct d3d9_stateblock *object;
2295  HRESULT hr;
2296 
2297  TRACE("iface %p, stateblock %p.\n", iface, stateblock);
2298 
2302  if (FAILED(hr))
2303  {
2304  WARN("Failed to end the state block, hr %#x.\n", hr);
2305  return hr;
2306  }
2307 
2308  if (!(object = heap_alloc_zero(sizeof(*object))))
2309  {
2313  return E_OUTOFMEMORY;
2314  }
2315 
2317  if (FAILED(hr))
2318  {
2319  WARN("Failed to initialize stateblock, hr %#x.\n", hr);
2323  heap_free(object);
2324  return hr;
2325  }
2326 
2327  TRACE("Created stateblock %p.\n", object);
2328  *stateblock = &object->IDirect3DStateBlock9_iface;
2329 
2330  return D3D_OK;
2331 }
2332 
2333 static HRESULT WINAPI d3d9_device_SetClipStatus(IDirect3DDevice9Ex *iface, const D3DCLIPSTATUS9 *clip_status)
2334 {
2336  HRESULT hr;
2337 
2338  TRACE("iface %p, clip_status %p.\n", iface, clip_status);
2339 
2341  hr = wined3d_device_set_clip_status(device->wined3d_device, (const struct wined3d_clip_status *)clip_status);
2343 
2344  return hr;
2345 }
2346 
2347 static HRESULT WINAPI d3d9_device_GetClipStatus(IDirect3DDevice9Ex *iface, D3DCLIPSTATUS9 *clip_status)
2348 {
2350  HRESULT hr;
2351 
2352  TRACE("iface %p, clip_status %p.\n", iface, clip_status);
2353 
2355  hr = wined3d_device_get_clip_status(device->wined3d_device, (struct wined3d_clip_status *)clip_status);
2357 
2358  return hr;
2359 }
2360 
2361 static HRESULT WINAPI d3d9_device_GetTexture(IDirect3DDevice9Ex *iface, DWORD stage, IDirect3DBaseTexture9 **texture)
2362 {
2365  struct d3d9_texture *texture_impl;
2366 
2367  TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
2368 
2369  if (!texture)
2370  return D3DERR_INVALIDCALL;
2371 
2373  if ((wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
2374  {
2376  *texture = &texture_impl->IDirect3DBaseTexture9_iface;
2378  }
2379  else
2380  {
2381  *texture = NULL;
2382  }
2384 
2385  return D3D_OK;
2386 }
2387 
2388 static HRESULT WINAPI d3d9_device_SetTexture(IDirect3DDevice9Ex *iface, DWORD stage, IDirect3DBaseTexture9 *texture)
2389 {
2391  struct d3d9_texture *texture_impl;
2392  HRESULT hr;
2393 
2394  TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
2395 
2397 
2399  hr = wined3d_device_set_texture(device->wined3d_device, stage,
2400  texture_impl ? texture_impl->wined3d_texture : NULL);
2402 
2403  return hr;
2404 }
2405 
2407 {
2408  WINED3D_TSS_INVALID, /* 0, unused */
2409  WINED3D_TSS_COLOR_OP, /* 1, D3DTSS_COLOROP */
2410  WINED3D_TSS_COLOR_ARG1, /* 2, D3DTSS_COLORARG1 */
2411  WINED3D_TSS_COLOR_ARG2, /* 3, D3DTSS_COLORARG2 */
2412  WINED3D_TSS_ALPHA_OP, /* 4, D3DTSS_ALPHAOP */
2413  WINED3D_TSS_ALPHA_ARG1, /* 5, D3DTSS_ALPHAARG1 */
2414  WINED3D_TSS_ALPHA_ARG2, /* 6, D3DTSS_ALPHAARG2 */
2415  WINED3D_TSS_BUMPENV_MAT00, /* 7, D3DTSS_BUMPENVMAT00 */
2416  WINED3D_TSS_BUMPENV_MAT01, /* 8, D3DTSS_BUMPENVMAT01 */
2417  WINED3D_TSS_BUMPENV_MAT10, /* 9, D3DTSS_BUMPENVMAT10 */
2418  WINED3D_TSS_BUMPENV_MAT11, /* 10, D3DTSS_BUMPENVMAT11 */
2419  WINED3D_TSS_TEXCOORD_INDEX, /* 11, D3DTSS_TEXCOORDINDEX */
2420  WINED3D_TSS_INVALID, /* 12, unused */
2421  WINED3D_TSS_INVALID, /* 13, unused */
2422  WINED3D_TSS_INVALID, /* 14, unused */
2423  WINED3D_TSS_INVALID, /* 15, unused */
2424  WINED3D_TSS_INVALID, /* 16, unused */
2425  WINED3D_TSS_INVALID, /* 17, unused */
2426  WINED3D_TSS_INVALID, /* 18, unused */
2427  WINED3D_TSS_INVALID, /* 19, unused */
2428  WINED3D_TSS_INVALID, /* 20, unused */
2429  WINED3D_TSS_INVALID, /* 21, unused */
2430  WINED3D_TSS_BUMPENV_LSCALE, /* 22, D3DTSS_BUMPENVLSCALE */
2431  WINED3D_TSS_BUMPENV_LOFFSET, /* 23, D3DTSS_BUMPENVLOFFSET */
2432  WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
2433  WINED3D_TSS_INVALID, /* 25, unused */
2434  WINED3D_TSS_COLOR_ARG0, /* 26, D3DTSS_COLORARG0 */
2435  WINED3D_TSS_ALPHA_ARG0, /* 27, D3DTSS_ALPHAARG0 */
2436  WINED3D_TSS_RESULT_ARG, /* 28, D3DTSS_RESULTARG */
2437  WINED3D_TSS_INVALID, /* 29, unused */
2438  WINED3D_TSS_INVALID, /* 30, unused */
2439  WINED3D_TSS_INVALID, /* 31, unused */
2440  WINED3D_TSS_CONSTANT, /* 32, D3DTSS_CONSTANT */
2441 };
2442 
2443 static HRESULT WINAPI d3d9_device_GetTextureStageState(IDirect3DDevice9Ex *iface,
2445 {
2447 
2448  TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, stage, state, value);
2449 
2450  if (state >= ARRAY_SIZE(tss_lookup))
2451  {
2452  WARN("Invalid state %#x passed.\n", state);
2453  return D3D_OK;
2454  }
2455 
2459 
2460  return D3D_OK;
2461 }
2462 
2463 static HRESULT WINAPI d3d9_device_SetTextureStageState(IDirect3DDevice9Ex *iface,
2465 {
2467 
2468  TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, stage, state, value);
2469 
2470  if (state >= ARRAY_SIZE(tss_lookup))
2471  {
2472  WARN("Invalid state %#x passed.\n", state);
2473  return D3D_OK;
2474  }
2475 
2479 
2480  return D3D_OK;
2481 }
2482 
2483 static HRESULT WINAPI d3d9_device_GetSamplerState(IDirect3DDevice9Ex *iface,
2485 {
2487 
2488  TRACE("iface %p, sampler %u, state %#x, value %p.\n", iface, sampler, state, value);
2489 
2493 
2494  return D3D_OK;
2495 }
2496 
2499 {
2501 
2502  TRACE("iface %p, sampler %u, state %#x, value %#x.\n", iface, sampler, state, value);
2503 
2507 
2508  return D3D_OK;
2509 }
2510 
2511 static HRESULT WINAPI d3d9_device_ValidateDevice(IDirect3DDevice9Ex *iface, DWORD *pass_count)
2512 {
2514  HRESULT hr;
2515 
2516  TRACE("iface %p, pass_count %p.\n", iface, pass_count);
2517 
2519  hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
2521 
2522  return hr;
2523 }
2524 
2525 static HRESULT WINAPI d3d9_device_SetPaletteEntries(IDirect3DDevice9Ex *iface,
2526  UINT palette_idx, const PALETTEENTRY *entries)
2527 {
2528  WARN("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries);
2529 
2530  /* The d3d9 palette API is non-functional on Windows. Getters and setters are implemented,
2531  * and some drivers allow the creation of P8 surfaces. These surfaces can be copied to
2532  * other P8 surfaces with StretchRect, but cannot be converted to (A)RGB.
2533  *
2534  * Some older(dx7) cards may have support for P8 textures, but games cannot rely on this. */
2535  return D3D_OK;
2536 }
2537 
2538 static HRESULT WINAPI d3d9_device_GetPaletteEntries(IDirect3DDevice9Ex *iface,
2539  UINT palette_idx, PALETTEENTRY *entries)
2540 {
2541  FIXME("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries);
2542 
2543  return D3DERR_INVALIDCALL;
2544 }
2545 
2546 static HRESULT WINAPI d3d9_device_SetCurrentTexturePalette(IDirect3DDevice9Ex *iface, UINT palette_idx)
2547 {
2548  WARN("iface %p, palette_idx %u unimplemented.\n", iface, palette_idx);
2549 
2550  return D3D_OK;
2551 }
2552 
2553 static HRESULT WINAPI d3d9_device_GetCurrentTexturePalette(IDirect3DDevice9Ex *iface, UINT *palette_idx)
2554 {
2555  FIXME("iface %p, palette_idx %p.\n", iface, palette_idx);
2556 
2557  return D3DERR_INVALIDCALL;
2558 }
2559 
2560 static HRESULT WINAPI d3d9_device_SetScissorRect(IDirect3DDevice9Ex *iface, const RECT *rect)
2561 {
2563 
2564  TRACE("iface %p, rect %p.\n", iface, rect);
2565 
2567  wined3d_device_set_scissor_rects(device->wined3d_device, 1, rect);
2569 
2570  return D3D_OK;
2571 }
2572 
2573 static HRESULT WINAPI d3d9_device_GetScissorRect(IDirect3DDevice9Ex *iface, RECT *rect)
2574 {
2576 
2577  TRACE("iface %p, rect %p.\n", iface, rect);
2578 
2580  wined3d_device_get_scissor_rects(device->wined3d_device, NULL, rect);
2582 
2583  return D3D_OK;
2584 }
2585 
2586 static HRESULT WINAPI d3d9_device_SetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface, BOOL software)
2587 {
2589 
2590  TRACE("iface %p, software %#x.\n", iface, software);
2591 
2593  wined3d_device_set_software_vertex_processing(device->wined3d_device, software);
2595 
2596  return D3D_OK;
2597 }
2598 
2599 static BOOL WINAPI d3d9_device_GetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface)
2600 {
2602  BOOL ret;
2603 
2604  TRACE("iface %p.\n", iface);
2605 
2609 
2610  return ret;
2611 }
2612 
2613 static HRESULT WINAPI d3d9_device_SetNPatchMode(IDirect3DDevice9Ex *iface, float segment_count)
2614 {
2616  HRESULT hr;
2617 
2618  TRACE("iface %p, segment_count %.8e.\n", iface, segment_count);
2619 
2621  hr = wined3d_device_set_npatch_mode(device->wined3d_device, segment_count);
2623 
2624  return hr;
2625 }
2626 
2627 static float WINAPI d3d9_device_GetNPatchMode(IDirect3DDevice9Ex *iface)
2628 {
2630  float ret;
2631 
2632  TRACE("iface %p.\n", iface);
2633 
2635  ret = wined3d_device_get_npatch_mode(device->wined3d_device);
2637 
2638  return ret;
2639 }
2640 
2641 /* wined3d critical section must be taken by the caller. */
2643 {
2644  struct wined3d_texture *texture;
2645  unsigned int i, stage;
2646 
2647  for (i = 0; i < D3D9_MAX_TEXTURE_UNITS; ++i)
2648  {
2649  stage = i >= 16 ? i - 16 + D3DVERTEXTEXTURESAMPLER0 : i;
2650  if ((texture = wined3d_device_get_texture(device->wined3d_device, stage)))
2652  }
2653 }
2654 
2655 static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface,
2656  D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count)
2657 {
2659  HRESULT hr;
2660 
2661  TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n",
2662  iface, primitive_type, start_vertex, primitive_count);
2663 
2665  if (!device->has_vertex_declaration)
2666  {
2668  WARN("Called without a valid vertex declaration set.\n");
2669  return D3DERR_INVALIDCALL;
2670  }
2672  wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
2673  hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex,
2674  vertex_count_from_primitive_count(primitive_type, primitive_count));
2675  if (SUCCEEDED(hr))
2678 
2679  return hr;
2680 }
2681 
2682 static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface,
2683  D3DPRIMITIVETYPE primitive_type, INT base_vertex_idx, UINT min_vertex_idx,
2684  UINT vertex_count, UINT start_idx, UINT primitive_count)
2685 {
2687  HRESULT hr;
2688 
2689  TRACE("iface %p, primitive_type %#x, base_vertex_idx %u, min_vertex_idx %u, "
2690  "vertex_count %u, start_idx %u, primitive_count %u.\n",
2691  iface, primitive_type, base_vertex_idx, min_vertex_idx,
2692  vertex_count, start_idx, primitive_count);
2693 
2695  if (!device->has_vertex_declaration)
2696  {
2698  WARN("Called without a valid vertex declaration set.\n");
2699  return D3DERR_INVALIDCALL;
2700  }
2702  wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx);
2703  wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
2704  hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, start_idx,
2705  vertex_count_from_primitive_count(primitive_type, primitive_count));
2706  if (SUCCEEDED(hr))
2709 
2710  return hr;
2711 }
2712 
2713 /* The caller is responsible for wined3d locking */
2715 {
2716  HRESULT hr;
2717 
2718  if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
2719  {
2720  UINT size = max(device->vertex_buffer_size * 2, min_size);
2721  struct wined3d_buffer_desc desc;
2722  struct wined3d_buffer *buffer;
2723 
2724  TRACE("Growing vertex buffer to %u bytes.\n", size);
2725 
2726  desc.byte_width = size;
2728  desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
2730  desc.misc_flags = 0;
2731  desc.structure_byte_stride = 0;
2732 
2733  if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
2735  {
2736  ERR("Failed to create vertex buffer, hr %#x.\n", hr);
2737  return hr;
2738  }
2739 
2740  if (device->vertex_buffer)
2741  wined3d_buffer_decref(device->vertex_buffer);
2742 
2743  device->vertex_buffer = buffer;
2744  device->vertex_buffer_size = size;
2745  device->vertex_buffer_pos = 0;
2746  }
2747  return D3D_OK;
2748 }
2749 
2750 static HRESULT WINAPI d3d9_device_DrawPrimitiveUP(IDirect3DDevice9Ex *iface,
2751  D3DPRIMITIVETYPE primitive_type, UINT primitive_count, const void *data, UINT stride)
2752 {
2754  HRESULT hr;
2755  UINT vtx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
2757  struct wined3d_box wined3d_box = {0};
2758  UINT size = vtx_count * stride;
2759  struct wined3d_resource *vb;
2760  UINT vb_pos, align;
2761 
2762  TRACE("iface %p, primitive_type %#x, primitive_count %u, data %p, stride %u.\n",
2763  iface, primitive_type, primitive_count, data, stride);
2764 
2765  if (!primitive_count)
2766  {
2767  WARN("primitive_count is 0, returning D3D_OK\n");
2768  return D3D_OK;
2769  }
2770 
2772 
2773  if (!device->has_vertex_declaration)
2774  {
2776  WARN("Called without a valid vertex declaration set.\n");
2777  return D3DERR_INVALIDCALL;
2778  }
2779 
2781  if (FAILED(hr))
2782  goto done;
2783 
2784  vb_pos = device->vertex_buffer_pos;
2785  align = vb_pos % stride;
2786  if (align) align = stride - align;
2787  if (vb_pos + size + align > device->vertex_buffer_size)
2788  vb_pos = 0;
2789  else
2790  vb_pos += align;
2791 
2792  wined3d_box.left = vb_pos;
2793  wined3d_box.right = vb_pos + size;
2794  vb = wined3d_buffer_get_resource(device->vertex_buffer);
2797  goto done;
2799  wined3d_resource_unmap(vb, 0);
2800  device->vertex_buffer_pos = vb_pos + size;
2801 
2802  hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
2803  if (FAILED(hr))
2804  goto done;
2805 
2807  wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
2808  hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vtx_count);
2809  wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
2810  if (SUCCEEDED(hr))
2812 
2813 done:
2815  return hr;
2816 }
2817 
2818 /* The caller is responsible for wined3d locking */
2820 {
2821  HRESULT hr;
2822 
2823  if (device->index_buffer_size < min_size || !device->index_buffer)
2824  {
2825  UINT size = max(device->index_buffer_size * 2, min_size);
2826  struct wined3d_buffer_desc desc;
2827  struct wined3d_buffer *buffer;
2828 
2829  TRACE("Growing index buffer to %u bytes.\n", size);
2830 
2831  desc.byte_width = size;
2833  desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
2835  desc.misc_flags = 0;
2836  desc.structure_byte_stride = 0;
2837 
2838  if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
2840  {
2841  ERR("Failed to create index buffer, hr %#x.\n", hr);
2842  return hr;
2843  }
2844 
2845  if (device->index_buffer)
2846  wined3d_buffer_decref(device->index_buffer);
2847 
2848  device->index_buffer = buffer;
2849  device->index_buffer_size = size;
2850  device->index_buffer_pos = 0;
2851  }
2852  return D3D_OK;
2853 }
2854 
2855 static HRESULT WINAPI d3d9_device_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *iface,
2856  D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count,
2857  UINT primitive_count, const void *index_data, D3DFORMAT index_format,
2858  const void *vertex_data, UINT vertex_stride)
2859 {
2860  UINT idx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
2862  UINT idx_fmt_size = index_format == D3DFMT_INDEX16 ? 2 : 4;
2863  UINT vtx_size = vertex_count * vertex_stride;
2864  UINT idx_size = idx_count * idx_fmt_size;
2866  struct wined3d_box wined3d_box = {0};
2867  struct wined3d_resource *ib, *vb;
2868  UINT vb_pos, ib_pos, align;
2869  HRESULT hr;
2870 
2871  TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, primitive_count %u, "
2872  "index_data %p, index_format %#x, vertex_data %p, vertex_stride %u.\n",
2873  iface, primitive_type, min_vertex_idx, vertex_count, primitive_count,
2874  index_data, index_format, vertex_data, vertex_stride);
2875 
2876  if (!primitive_count)
2877  {
2878  WARN("primitive_count is 0, returning D3D_OK.\n");
2879  return D3D_OK;
2880  }
2881 
2883 
2884  if (!device->has_vertex_declaration)
2885  {
2887  WARN("Called without a valid vertex declaration set.\n");
2888  return D3DERR_INVALIDCALL;
2889  }
2890 
2892  if (FAILED(hr))
2893  goto done;
2894 
2895  vb_pos = device->vertex_buffer_pos;
2896  align = vb_pos % vertex_stride;
2897  if (align) align = vertex_stride - align;
2898  if (vb_pos + vtx_size + align > device->vertex_buffer_size)
2899  vb_pos = 0;
2900  else
2901  vb_pos += align;
2902 
2903  wined3d_box.left = vb_pos;
2904  wined3d_box.right = vb_pos + vtx_size;
2905  vb = wined3d_buffer_get_resource(device->vertex_buffer);
2908  goto done;
2909  memcpy(wined3d_map_desc.data, (char *)vertex_data + min_vertex_idx * vertex_stride, vtx_size);
2910  wined3d_resource_unmap(vb, 0);
2911  device->vertex_buffer_pos = vb_pos + vtx_size;
2912 
2914  if (FAILED(hr))
2915  goto done;
2916 
2917  ib_pos = device->index_buffer_pos;
2918  align = ib_pos % idx_fmt_size;
2919  if (align) align = idx_fmt_size - align;
2920  if (ib_pos + idx_size + align > device->index_buffer_size)
2921  ib_pos = 0;
2922  else
2923  ib_pos += align;
2924 
2925  wined3d_box.left = ib_pos;
2926  wined3d_box.right = ib_pos + idx_size;
2927  ib = wined3d_buffer_get_resource(device->index_buffer);
2930  goto done;
2931  memcpy(wined3d_map_desc.data, index_data, idx_size);
2932  wined3d_resource_unmap(ib, 0);
2933  device->index_buffer_pos = ib_pos + idx_size;
2934 
2935  hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vertex_stride);
2936  if (FAILED(hr))
2937  goto done;
2938 
2940  wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer,
2941  wined3dformat_from_d3dformat(index_format), 0);
2942  wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vertex_stride - min_vertex_idx);
2943 
2944  wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
2945  hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / idx_fmt_size, idx_count);
2946 
2947  wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
2949  wined3d_device_set_base_vertex_index(device->wined3d_device, 0);
2950 
2951  if (SUCCEEDED(hr))
2953 
2954 done:
2956  return hr;
2957 }
2958 
2959 static HRESULT WINAPI d3d9_device_ProcessVertices(IDirect3DDevice9Ex *iface,
2960  UINT src_start_idx, UINT dst_idx, UINT vertex_count, IDirect3DVertexBuffer9 *dst_buffer,
2961  IDirect3DVertexDeclaration9 *declaration, DWORD flags)
2962 {
2964  struct d3d9_vertexbuffer *dst_impl = unsafe_impl_from_IDirect3DVertexBuffer9(dst_buffer);
2966  HRESULT hr;
2967 
2968  TRACE("iface %p, src_start_idx %u, dst_idx %u, vertex_count %u, dst_buffer %p, declaration %p, flags %#x.\n",
2969  iface, src_start_idx, dst_idx, vertex_count, dst_buffer, declaration, flags);
2970 
2972  hr = wined3d_device_process_vertices(device->wined3d_device, src_start_idx, dst_idx, vertex_count,
2973  dst_impl->wined3d_buffer, decl_impl ? decl_impl->wined3d_declaration : NULL,
2974  flags, dst_impl->fvf);
2976 
2977  return hr;
2978 }
2979 
2980 static HRESULT WINAPI d3d9_device_CreateVertexDeclaration(IDirect3DDevice9Ex *iface,
2981  const D3DVERTEXELEMENT9 *elements, IDirect3DVertexDeclaration9 **declaration)
2982 {
2985  HRESULT hr;
2986 
2987  TRACE("iface %p, elements %p, declaration %p.\n", iface, elements, declaration);
2988 
2989  if (!declaration)
2990  {
2991  WARN("Caller passed a NULL declaration, returning D3DERR_INVALIDCALL.\n");
2992  return D3DERR_INVALIDCALL;
2993  }
2994 
2996  *declaration = &object->IDirect3DVertexDeclaration9_iface;
2997 
2998  return hr;
2999 }
3000 
3001 static HRESULT WINAPI d3d9_device_SetVertexDeclaration(IDirect3DDevice9Ex *iface,
3002  IDirect3DVertexDeclaration9 *declaration)
3003 {
3006 
3007  TRACE("iface %p, declaration %p.\n", iface, declaration);
3008 
3011  decl_impl ? decl_impl->wined3d_declaration : NULL);
3012  device->has_vertex_declaration = !!decl_impl;
3014 
3015  return D3D_OK;
3016 }
3017 
3018 static HRESULT WINAPI d3d9_device_GetVertexDeclaration(IDirect3DDevice9Ex *iface,
3019  IDirect3DVertexDeclaration9 **declaration)
3020 {
3022  struct wined3d_vertex_declaration *wined3d_declaration;
3023  struct d3d9_vertex_declaration *declaration_impl;
3024 
3025  TRACE("iface %p, declaration %p.\n", iface, declaration);
3026 
3027  if (!declaration) return D3DERR_INVALIDCALL;
3028 
3031  {
3033  *declaration = &declaration_impl->IDirect3DVertexDeclaration9_iface;
3035  }
3036  else
3037  {
3038  *declaration = NULL;
3039  }
3041 
3042  TRACE("Returning %p.\n", *declaration);
3043  return D3D_OK;
3044 }
3045 
3047 {
3048  struct wined3d_vertex_declaration *wined3d_declaration;
3049  struct fvf_declaration *fvf_decls = device->fvf_decls;
3050  struct d3d9_vertex_declaration *d3d9_declaration;
3052  int p, low, high; /* deliberately signed */
3053  HRESULT hr;
3054 
3055  TRACE("Searching for declaration for fvf %08x... ", fvf);
3056 
3057  low = 0;
3058  high = device->fvf_decl_count - 1;
3059  while (low <= high)
3060  {
3061  p = (low + high) >> 1;
3062  TRACE("%d ", p);
3063 
3064  if (fvf_decls[p].fvf == fvf)
3065  {
3066  TRACE("found %p.\n", fvf_decls[p].decl);
3067  return fvf_decls[p].decl;
3068  }
3069 
3070  if (fvf_decls[p].fvf < fvf)
3071  low = p + 1;
3072  else
3073  high = p - 1;
3074  }
3075  TRACE("not found. Creating and inserting at position %d.\n", low);
3076 
3078  return NULL;
3079 
3080  hr = d3d9_vertex_declaration_create(device, elements, &d3d9_declaration);
3082  if (FAILED(hr))
3083  return NULL;
3084 
3085  if (device->fvf_decl_size == device->fvf_decl_count)
3086  {
3087  UINT grow = max(device->fvf_decl_size / 2, 8);
3088 
3089  if (!(fvf_decls = heap_realloc(fvf_decls, sizeof(*fvf_decls) * (device->fvf_decl_size + grow))))
3090  {
3092  return NULL;
3093  }
3094  device->fvf_decls = fvf_decls;
3095  device->fvf_decl_size += grow;
3096  }
3097 
3098  d3d9_declaration->fvf = fvf;
3099  wined3d_declaration = d3d9_declaration->wined3d_declaration;
3102 
3103  memmove(fvf_decls + low + 1, fvf_decls + low, sizeof(*fvf_decls) * (device->fvf_decl_count - low));
3104  fvf_decls[low].decl = wined3d_declaration;
3105  fvf_decls[low].fvf = fvf;
3106  ++device->fvf_decl_count;
3107 
3108  TRACE("Returning %p. %u declarations in array.\n", wined3d_declaration, device->fvf_decl_count);
3109 
3110  return wined3d_declaration;
3111 }
3112 
3113 static HRESULT WINAPI d3d9_device_SetFVF(IDirect3DDevice9Ex *iface, DWORD fvf)
3114 {
3116  struct wined3d_vertex_declaration *decl;
3117 
3118  TRACE("iface %p, fvf %#x.\n", iface, fvf);
3119 
3120  if (!fvf)
3121  {
3122  WARN("%#x is not a valid FVF.\n", fvf);
3123  return D3D_OK;
3124  }
3125 
3127  if (!(decl = device_get_fvf_declaration(device, fvf)))
3128  {
3130  ERR("Failed to create a vertex declaration for fvf %#x.\n", fvf);
3132  }
3133 
3134  wined3d_device_set_vertex_declaration(device->wined3d_device, decl);
3135  device->has_vertex_declaration = TRUE;
3137 
3138  return D3D_OK;
3139 }
3140 
3141 static HRESULT WINAPI d3d9_device_GetFVF(IDirect3DDevice9Ex *iface, DWORD *fvf)
3142 {
3144  struct wined3d_vertex_declaration *wined3d_declaration;
3145  struct d3d9_vertex_declaration *d3d9_declaration;
3146 
3147  TRACE("iface %p, fvf %p.\n", iface, fvf);
3148 
3151  {
3153  *fvf = d3d9_declaration->fvf;
3154  }
3155  else
3156  {
3157  *fvf = 0;
3158  }
3160 
3161  TRACE("Returning FVF %#x.\n", *fvf);
3162 
3163  return D3D_OK;
3164 }
3165 
3166 static HRESULT WINAPI d3d9_device_CreateVertexShader(IDirect3DDevice9Ex *iface,
3167  const DWORD *byte_code, IDirect3DVertexShader9 **shader)
3168 {
3170  struct d3d9_vertexshader *object;
3171  HRESULT hr;
3172 
3173  TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
3174 
3175  if (!(object = heap_alloc_zero(sizeof(*object))))
3176  return E_OUTOFMEMORY;
3177 
3178  hr = vertexshader_init(object, device, byte_code);
3179  if (FAILED(hr))
3180  {
3181  WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
3182  heap_free(object);
3183  return hr;
3184  }
3185 
3186  TRACE("Created vertex shader %p.\n", object);
3187  *shader = &object->IDirect3DVertexShader9_iface;
3188 
3189  return D3D_OK;
3190 }
3191 
3192 static HRESULT WINAPI d3d9_device_SetVertexShader(IDirect3DDevice9Ex *iface, IDirect3DVertexShader9 *shader)
3193 {
3196 
3197  TRACE("iface %p, shader %p.\n", iface, shader);
3198 
3200  wined3d_device_set_vertex_shader(device->wined3d_device,
3201  shader_obj ? shader_obj->wined3d_shader : NULL);
3203 
3204  return D3D_OK;
3205 }
3206 
3207 static HRESULT WINAPI d3d9_device_GetVertexShader(IDirect3DDevice9Ex *iface, IDirect3DVertexShader9 **shader)
3208 {
3210  struct d3d9_vertexshader *shader_impl;
3212 
3213  TRACE("iface %p, shader %p.\n", iface, shader);
3214 
3216  if ((wined3d_shader = wined3d_device_get_vertex_shader(device->wined3d_device)))
3217  {
3219  *shader = &shader_impl->IDirect3DVertexShader9_iface;
3221  }
3222  else
3223  {
3224  *shader = NULL;
3225  }
3227 
3228  TRACE("Returning %p.\n", *shader);
3229 
3230  return D3D_OK;
3231 }
3232 
3233 static HRESULT WINAPI d3d9_device_SetVertexShaderConstantF(IDirect3DDevice9Ex *iface,
3234  UINT reg_idx, const float *data, UINT count)
3235 {
3237  HRESULT hr;
3238 
3239  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3240 
3241  if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF)
3242  {
3243  WARN("Trying to access %u constants, but d3d9 only supports %u\n",
3245  return D3DERR_INVALIDCALL;
3246  }
3247 
3249  hr = wined3d_device_set_vs_consts_f(device->wined3d_device,
3250  reg_idx, count, (const struct wined3d_vec4 *)data);
3252 
3253  return hr;
3254 }
3255 
3256 static HRESULT WINAPI d3d9_device_GetVertexShaderConstantF(IDirect3DDevice9Ex *iface,
3257  UINT reg_idx, float *data, UINT count)
3258 {
3260  HRESULT hr;
3261 
3262  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3263 
3264  if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF)
3265  {
3266  WARN("Trying to access %u constants, but d3d9 only supports %u\n",
3268  return D3DERR_INVALIDCALL;
3269  }
3270 
3272  hr = wined3d_device_get_vs_consts_f(device->wined3d_device,
3273  reg_idx, count, (struct wined3d_vec4 *)data);
3275 
3276  return hr;
3277 }
3278 
3279 static HRESULT WINAPI d3d9_device_SetVertexShaderConstantI(IDirect3DDevice9Ex *iface,
3280  UINT reg_idx, const int *data, UINT count)
3281 {
3283  HRESULT hr;
3284 
3285  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3286 
3288  hr = wined3d_device_set_vs_consts_i(device->wined3d_device,
3289  reg_idx, count, (const struct wined3d_ivec4 *)data);
3291 
3292  return hr;
3293 }
3294 
3295 static HRESULT WINAPI d3d9_device_GetVertexShaderConstantI(IDirect3DDevice9Ex *iface,
3296  UINT reg_idx, int *data, UINT count)
3297 {
3299  HRESULT hr;
3300 
3301  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3302 
3304  hr = wined3d_device_get_vs_consts_i(device->wined3d_device,
3305  reg_idx, count, (struct wined3d_ivec4 *)data);
3307 
3308  return hr;
3309 }
3310 
3311 static HRESULT WINAPI d3d9_device_SetVertexShaderConstantB(IDirect3DDevice9Ex *iface,
3312  UINT reg_idx, const BOOL *data, UINT count)
3313 {
3315  HRESULT hr;
3316 
3317  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3318 
3320  hr = wined3d_device_set_vs_consts_b(device->wined3d_device, reg_idx, count, data);
3322 
3323  return hr;
3324 }
3325 
3326 static HRESULT WINAPI d3d9_device_GetVertexShaderConstantB(IDirect3DDevice9Ex *iface,
3327  UINT reg_idx, BOOL *data, UINT count)
3328 {
3330  HRESULT hr;
3331 
3332  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3333 
3335  hr = wined3d_device_get_vs_consts_b(device->wined3d_device, reg_idx, count, data);
3337 
3338  return hr;
3339 }
3340 
3341 static HRESULT WINAPI d3d9_device_SetStreamSource(IDirect3DDevice9Ex *iface,
3342  UINT stream_idx, IDirect3DVertexBuffer9 *buffer, UINT offset, UINT stride)
3343 {
3346  HRESULT hr;
3347 
3348  TRACE("iface %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
3349  iface, stream_idx, buffer, offset, stride);
3350 
3352  hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx,
3353  buffer_impl ? buffer_impl->wined3d_buffer : NULL, offset, stride);
3355 
3356  return hr;
3357 }
3358 
3359 static HRESULT WINAPI d3d9_device_GetStreamSource(IDirect3DDevice9Ex *iface,
3360  UINT stream_idx, IDirect3DVertexBuffer9 **buffer, UINT *offset, UINT *stride)
3361 {
3363  struct d3d9_vertexbuffer *buffer_impl;
3365  HRESULT hr;
3366 
3367  TRACE("iface %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
3368  iface, stream_idx, buffer, offset, stride);
3369 
3370  if (!buffer)
3371  return D3DERR_INVALIDCALL;
3372 
3374  hr = wined3d_device_get_stream_source(device->wined3d_device, stream_idx, &wined3d_buffer, offset, stride);
3375  if (SUCCEEDED(hr) && wined3d_buffer)
3376  {
3378  *buffer = &buffer_impl->IDirect3DVertexBuffer9_iface;
3380  }
3381  else
3382  {
3383  if (FAILED(hr))
3384  FIXME("Call to GetStreamSource failed %p %p\n", offset, stride);
3385  *buffer = NULL;
3386  }
3388 
3389  return hr;
3390 }
3391 
3392 static HRESULT WINAPI d3d9_device_SetStreamSourceFreq(IDirect3DDevice9Ex *iface, UINT stream_idx, UINT freq)
3393 {
3395  HRESULT hr;
3396 
3397  TRACE("iface %p, stream_idx %u, freq %u.\n", iface, stream_idx, freq);
3398 
3400  hr = wined3d_device_set_stream_source_freq(device->wined3d_device, stream_idx, freq);
3402 
3403  return hr;
3404 }
3405 
3406 static HRESULT WINAPI d3d9_device_GetStreamSourceFreq(IDirect3DDevice9Ex *iface, UINT stream_idx, UINT *freq)
3407 {
3409  HRESULT hr;
3410 
3411  TRACE("iface %p, stream_idx %u, freq %p.\n", iface, stream_idx, freq);
3412 
3414  hr = wined3d_device_get_stream_source_freq(device->wined3d_device, stream_idx, freq);
3416 
3417  return hr;
3418 }
3419 
3420 static HRESULT WINAPI d3d9_device_SetIndices(IDirect3DDevice9Ex *iface, IDirect3DIndexBuffer9 *buffer)
3421 {
3424 
3425  TRACE("iface %p, buffer %p.\n", iface, buffer);
3426 
3428  wined3d_device_set_index_buffer(device->wined3d_device,
3429  ib ? ib->wined3d_buffer : NULL, ib ? ib->format : WINED3DFMT_UNKNOWN, 0);
3431 
3432  return D3D_OK;
3433 }
3434 
3435 static HRESULT WINAPI d3d9_device_GetIndices(IDirect3DDevice9Ex *iface, IDirect3DIndexBuffer9 **buffer)
3436 {
3440  struct d3d9_indexbuffer *buffer_impl;
3441 
3442  TRACE("iface %p, buffer %p.\n", iface, buffer);
3443 
3444  if (!buffer)
3445  return D3DERR_INVALIDCALL;
3446 
3449  {
3451  *buffer = &buffer_impl->IDirect3DIndexBuffer9_iface;
3453  }
3454  else
3455  {
3456  *buffer = NULL;
3457  }
3459 
3460  return D3D_OK;
3461 }
3462 
3463 static HRESULT WINAPI d3d9_device_CreatePixelShader(IDirect3DDevice9Ex *iface,
3464  const DWORD *byte_code, IDirect3DPixelShader9 **shader)
3465 {
3467  struct d3d9_pixelshader *object;
3468  HRESULT hr;
3469 
3470  TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
3471 
3472  if (!(object = heap_alloc_zero(sizeof(*object))))
3473  {
3474  FIXME("Failed to allocate pixel shader memory.\n");
3475  return E_OUTOFMEMORY;
3476  }
3477 
3478  hr = pixelshader_init(object, device, byte_code);
3479  if (FAILED(hr))
3480  {
3481  WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
3482  heap_free(object);
3483  return hr;
3484  }
3485 
3486  TRACE("Created pixel shader %p.\n", object);
3487  *shader = &object->IDirect3DPixelShader9_iface;
3488 
3489  return D3D_OK;
3490 }
3491 
3492 static HRESULT WINAPI d3d9_device_SetPixelShader(IDirect3DDevice9Ex *iface, IDirect3DPixelShader9 *shader)
3493 {
3496 
3497  TRACE("iface %p, shader %p.\n", iface, shader);
3498 
3500  wined3d_device_set_pixel_shader(device->wined3d_device,
3501  shader_obj ? shader_obj->wined3d_shader : NULL);
3503 
3504  return D3D_OK;
3505 }
3506 
3507 static HRESULT WINAPI d3d9_device_GetPixelShader(IDirect3DDevice9Ex *iface, IDirect3DPixelShader9 **shader)
3508 {
3510  struct d3d9_pixelshader *shader_impl;
3512 
3513  TRACE("iface %p, shader %p.\n", iface, shader);
3514 
3515  if (!shader) return D3DERR_INVALIDCALL;
3516 
3518  if ((wined3d_shader = wined3d_device_get_pixel_shader(device->wined3d_device)))
3519  {
3521  *shader = &shader_impl->IDirect3DPixelShader9_iface;
3523  }
3524  else
3525  {
3526  *shader = NULL;
3527  }
3529 
3530  TRACE("Returning %p.\n", *shader);
3531 
3532  return D3D_OK;
3533 }
3534 
3535 static HRESULT WINAPI d3d9_device_SetPixelShaderConstantF(IDirect3DDevice9Ex *iface,
3536  UINT reg_idx, const float *data, UINT count)
3537 {
3539  HRESULT hr;
3540 
3541  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3542 
3544  hr = wined3d_device_set_ps_consts_f(device->wined3d_device,
3545  reg_idx, count, (const struct wined3d_vec4 *)data);
3547 
3548  return hr;
3549 }
3550 
3551 static HRESULT WINAPI d3d9_device_GetPixelShaderConstantF(IDirect3DDevice9Ex *iface,
3552  UINT reg_idx, float *data, UINT count)
3553 {
3555  HRESULT hr;
3556 
3557  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3558 
3560  hr = wined3d_device_get_ps_consts_f(device->wined3d_device,
3561  reg_idx, count, (struct wined3d_vec4 *)data);
3563 
3564  return hr;
3565 }
3566 
3567 static HRESULT WINAPI d3d9_device_SetPixelShaderConstantI(IDirect3DDevice9Ex *iface,
3568  UINT reg_idx, const int *data, UINT count)
3569 {
3571  HRESULT hr;
3572 
3573  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3574 
3576  hr = wined3d_device_set_ps_consts_i(device->wined3d_device,
3577  reg_idx, count, (const struct wined3d_ivec4 *)data);
3579 
3580  return hr;
3581 }
3582 
3583 static HRESULT WINAPI d3d9_device_GetPixelShaderConstantI(IDirect3DDevice9Ex *iface,
3584  UINT reg_idx, int *data, UINT count)
3585 {
3587  HRESULT hr;
3588 
3589  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3590 
3592  hr = wined3d_device_get_ps_consts_i(device->wined3d_device,
3593  reg_idx, count, (struct wined3d_ivec4 *)data);
3595 
3596  return hr;
3597 }
3598 
3599 static HRESULT WINAPI d3d9_device_SetPixelShaderConstantB(IDirect3DDevice9Ex *iface,
3600  UINT reg_idx, const BOOL *data, UINT count)
3601 {
3603  HRESULT hr;
3604 
3605  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3606 
3608  hr = wined3d_device_set_ps_consts_b(device->wined3d_device, reg_idx, count, data);
3610 
3611  return hr;
3612 }
3613 
3614 static HRESULT WINAPI d3d9_device_GetPixelShaderConstantB(IDirect3DDevice9Ex *iface,
3615  UINT reg_idx, BOOL *data, UINT count)
3616 {
3618  HRESULT hr;
3619 
3620  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3621 
3623  hr = wined3d_device_get_ps_consts_b(device->wined3d_device, reg_idx, count, data);
3625 
3626  return hr;
3627 }
3628 
3629 static HRESULT WINAPI d3d9_device_DrawRectPatch(IDirect3DDevice9Ex *iface, UINT handle,
3630  const float *segment_count, const D3DRECTPATCH_INFO *patch_info)
3631 {
3632  FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
3633  iface, handle, segment_count, patch_info);
3634  return D3D_OK;
3635 }
3636 
3637 static HRESULT WINAPI d3d9_device_DrawTriPatch(IDirect3DDevice9Ex *iface, UINT handle,
3638  const float *segment_count, const D3DTRIPATCH_INFO *patch_info)
3639 {
3640  FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
3641  iface, handle, segment_count, patch_info);
3642  return D3D_OK;
3643 }
3644 
3645 static HRESULT WINAPI d3d9_device_DeletePatch(IDirect3DDevice9Ex *iface, UINT handle)
3646 {
3647  FIXME("iface %p, handle %#x unimplemented.\n", iface, handle);
3648  return D3DERR_INVALIDCALL;
3649 }
3650 
3651 static HRESULT WINAPI d3d9_device_CreateQuery(IDirect3DDevice9Ex *iface, D3DQUERYTYPE type, IDirect3DQuery9 **query)
3652 {
3654  struct d3d9_query *object;
3655  HRESULT hr;
3656 
3657  TRACE("iface %p, type %#x, query %p.\n", iface, type, query);
3658 
3659  if (!(object = heap_alloc_zero(sizeof(*object))))
3660  return E_OUTOFMEMORY;
3661 
3662  hr = query_init(object, device, type);
3663  if (FAILED(hr))
3664  {
3665  WARN("Failed to initialize query, hr %#x.\n", hr);
3666  heap_free(object);
3667  return hr;
3668  }
3669 
3670  TRACE("Created query %p.\n", object);
3671  if (query) *query = &object->IDirect3DQuery9_iface;
3672  else IDirect3DQuery9_Release(&object->IDirect3DQuery9_iface);
3673 
3674  return D3D_OK;
3675 }
3676 
3677 static HRESULT WINAPI d3d9_device_SetConvolutionMonoKernel(IDirect3DDevice9Ex *iface,
3678  UINT width, UINT height, float *rows, float *columns)
3679 {
3680  FIXME("iface %p, width %u, height %u, rows %p, columns %p stub!\n",
3681  iface, width, height, rows, columns);
3682 
3683  return E_NOTIMPL;
3684 }
3685 
3686 static HRESULT WINAPI d3d9_device_ComposeRects(IDirect3DDevice9Ex *iface,
3687  IDirect3DSurface9 *src_surface, IDirect3DSurface9 *dst_surface, IDirect3DVertexBuffer9 *src_descs,
3688  UINT rect_count, IDirect3DVertexBuffer9 *dst_descs, D3DCOMPOSERECTSOP operation, INT offset_x, INT offset_y)
3689 {
3690  FIXME("iface %p, src_surface %p, dst_surface %p, src_descs %p, rect_count %u, "
3691  "dst_descs %p, operation %#x, offset_x %u, offset_y %u stub!\n",
3692  iface, src_surface, dst_surface, src_descs, rect_count,
3693  dst_descs, operation, offset_x, offset_y);
3694 
3695  return E_NOTIMPL;
3696 }
3697 
3698 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex *iface,
3699  const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
3700  const RGNDATA *dirty_region, DWORD flags)
3701 {
3703  struct d3d9_swapchain *swapchain;
3704  unsigned int i;
3705  HRESULT hr;
3706 
3707  TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n",
3708  iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect),
3709  dst_window_override, dirty_region, flags);
3710 
3711  if (device->device_state != D3D9_DEVICE_STATE_OK)
3712  return S_PRESENT_OCCLUDED;
3713 
3714  if (dirty_region)
3715  FIXME("Ignoring dirty_region %p.\n", dirty_region);
3716 
3718  for (i = 0; i < device->implicit_swapchain_count; ++i)
3719  {
3720  swapchain = device->implicit_swapchains[i];
3722  src_rect, dst_rect, dst_window_override, swapchain->swap_interval, flags)))
3723  {
3725  return hr;
3726  }
3727  }
3729 
3730  return D3D_OK;
3731 }
3732 
3733 static HRESULT WINAPI d3d9_device_GetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT *priority)
3734 {
3735  FIXME("iface %p, priority %p stub!\n", iface, priority);
3736 
3737  return E_NOTIMPL;
3738 }
3739 
3740 static HRESULT WINAPI d3d9_device_SetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT priority)
3741 {
3742  FIXME("iface %p, priority %d stub!\n", iface, priority);
3743 
3744  return E_NOTIMPL;
3745 }
3746 
3747 static HRESULT WINAPI d3d9_device_WaitForVBlank(IDirect3DDevice9Ex *iface, UINT swapchain_idx)
3748 {
3749  FIXME("iface %p, swapchain_idx %u stub!\n", iface, swapchain_idx);
3750 
3751  return E_NOTIMPL;
3752 }
3753 
3754 static HRESULT WINAPI d3d9_device_CheckResourceResidency(IDirect3DDevice9Ex *iface,
3755  IDirect3DResource9 **resources, UINT32 resource_count)
3756 {
3757  FIXME("iface %p, resources %p, resource_count %u stub!\n",
3758  iface, resources, resource_count);
3759 
3760  return E_NOTIMPL;
3761 }
3762 
3763 static HRESULT WINAPI d3d9_device_SetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT max_latency)
3764 {
3766 
3767  TRACE("iface %p, max_latency %u.\n", iface, max_latency);
3768 
3769  if (max_latency > 30)
3770  return D3DERR_INVALIDCALL;
3771 
3773  wined3d_device_set_max_frame_latency(device->wined3d_device, max_latency);
3775 
3776  return S_OK;
3777 }
3778 
3779 static HRESULT WINAPI d3d9_device_GetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT *max_latency)
3780 {
3782 
3783  TRACE("iface %p, max_latency %p.\n", iface, max_latency);
3784 
3786  *max_latency = wined3d_device_get_max_frame_latency(device->wined3d_device);
3788 
3789  return S_OK;
3790 }
3791 
3792 static HRESULT WINAPI d3d9_device_CheckDeviceState(IDirect3DDevice9Ex *iface, HWND dst_window)
3793 {
3795  struct wined3d_swapchain_desc swapchain_desc;
3796 
3797  TRACE("iface %p, dst_window %p.\n", iface, dst_window);
3798 
3800  wined3d_swapchain_get_desc(device->implicit_swapchains[0]->wined3d_swapchain, &swapchain_desc);
3802 
3803  if (swapchain_desc.windowed)
3804  return D3D_OK;
3805 
3806  /* FIXME: This is actually supposed to check if any other device is in
3807  * fullscreen mode. */
3808  if (dst_window != swapchain_desc.device_window)
3809  return device->device_state == D3D9_DEVICE_STATE_OK ? S_PRESENT_OCCLUDED : D3D_OK;
3810 
3811  return device->device_state == D3D9_DEVICE_STATE_OK ? D3D_OK : S_PRESENT_OCCLUDED;
3812 }
3813 
3814 static HRESULT WINAPI d3d9_device_CreateRenderTargetEx(IDirect3DDevice9Ex *iface,
3816  BOOL lockable, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage)
3817 {
3818  FIXME("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u, "
3819  "lockable %#x, surface %p, shared_handle %p, usage %#x stub!\n",
3821  lockable, surface, shared_handle, usage);
3822 
3823  *surface = NULL;
3824  if (shared_handle)
3825  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
3826 
3827  return E_NOTIMPL;
3828 }
3829 
3831  UINT width, UINT height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface,
3832  HANDLE *shared_handle, DWORD usage)
3833 {
3834  FIXME("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p, usage %#x stub!\n",
3835  iface, width, height, format, pool, surface, shared_handle, usage);
3836 
3837  return E_NOTIMPL;
3838 }
3839 
3840 static HRESULT WINAPI d3d9_device_CreateDepthStencilSurfaceEx(IDirect3DDevice9Ex *iface,
3842  BOOL discard, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage)
3843 {
3846 
3847  TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u, "
3848  "discard %#x, surface %p, shared_handle %p, usage %#x.\n",
3849  iface, width, height, format, multisample_type, multisample_quality,
3850  discard, surface, shared_handle, usage);
3851 
3853  {
3854  WARN("Invalid usage %#x.\n", usage);
3855  return D3DERR_INVALIDCALL;
3856  }
3857 
3858  if (shared_handle)
3859  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
3860 
3861  if (discard)
3863 
3864  *surface = NULL;
3866  D3DUSAGE_DEPTHSTENCIL | usage, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL);
3867 }
3868 
3869 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_ResetEx(IDirect3DDevice9Ex *iface,
3870  D3DPRESENT_PARAMETERS *present_parameters, D3DDISPLAYMODEEX *mode)
3871 {
3873 
3874  TRACE("iface %p, present_parameters %p, mode %p.\n", iface, present_parameters, mode);
3875 
3876  if (!present_parameters->Windowed == !mode)
3877  {
3878  WARN("Mode can be passed if and only if Windowed is FALSE.\n");
3879  return D3DERR_INVALIDCALL;
3880  }
3881 
3882  if (mode && (mode->Width != present_parameters->BackBufferWidth
3883  || mode->Height != present_parameters->BackBufferHeight))
3884  {
3885  WARN("Mode and back buffer mismatch (mode %ux%u, backbuffer %ux%u).\n",
3886  mode->Width, mode->Height,
3887  present_parameters->BackBufferWidth, present_parameters->BackBufferHeight);
3888  return D3DERR_INVALIDCALL;
3889  }
3890 
3891  return d3d9_device_reset(device, present_parameters, mode);
3892 }
3893 
3894 static HRESULT WINAPI d3d9_device_GetDisplayModeEx(IDirect3DDevice9Ex *iface,
3895  UINT swapchain_idx, D3DDISPLAYMODEEX *mode, D3DDISPLAYROTATION *rotation)
3896 {
3898  struct wined3d_display_mode wined3d_mode;
3899  HRESULT hr;
3900 
3901  TRACE("iface %p, swapchain_idx %u, mode %p, rotation %p.\n",
3902  iface, swapchain_idx, mode, rotation);
3903 
3904  if (mode->Size != sizeof(*mode))
3905  return D3DERR_INVALIDCALL;
3906 
3908  hr = wined3d_device_get_display_mode(device->wined3d_device, swapchain_idx, &wined3d_mode,
3909  (enum wined3d_display_rotation *)rotation);
3911 
3912  if (SUCCEEDED(hr))
3913  {
3914  mode->Width = wined3d_mode.width;
3915  mode->Height = wined3d_mode.height;
3916  mode->RefreshRate = wined3d_mode.refresh_rate;
3917  mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
3918  mode->ScanLineOrdering = wined3d_mode.scanline_ordering;
3919  }
3920 
3921  return hr;
3922 }
3923 
3924 static const struct IDirect3DDevice9ExVtbl d3d9_device_vtbl =
3925 {
3926  /* IUnknown */
3930  /* IDirect3DDevice9 */
4047  /* IDirect3DDevice9Ex */
4063 };
4064 
4066 {
4068 }
4069 
4070 static void CDECL