ReactOS  0.4.14-dev-593-g1793dcc
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)
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 = swapchain_desc->swap_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  const D3DPRESENT_PARAMETERS *present_parameters, BOOL extended)
275 {
276  D3DSWAPEFFECT highest_swapeffect = extended ? D3DSWAPEFFECT_FLIPEX : D3DSWAPEFFECT_COPY;
277  UINT highest_bb_count = extended ? 30 : 3;
278 
279  if (!present_parameters->SwapEffect || present_parameters->SwapEffect > highest_swapeffect)
280  {
281  WARN("Invalid swap effect %u passed.\n", present_parameters->SwapEffect);
282  return FALSE;
283  }
284  if (present_parameters->BackBufferCount > highest_bb_count
285  || (present_parameters->SwapEffect == D3DSWAPEFFECT_COPY
286  && present_parameters->BackBufferCount > 1))
287  {
288  WARN("Invalid backbuffer count %u.\n", present_parameters->BackBufferCount);
289  return FALSE;
290  }
291 
292  swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth;
293  swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight;
294  swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat);
295  swapchain_desc->backbuffer_count = max(1, present_parameters->BackBufferCount);
297  swapchain_desc->multisample_type = present_parameters->MultiSampleType;
298  swapchain_desc->multisample_quality = present_parameters->MultiSampleQuality;
299  swapchain_desc->swap_effect = wined3dswapeffect_from_d3dswapeffect(present_parameters->SwapEffect);
300  swapchain_desc->device_window = present_parameters->hDeviceWindow;
301  swapchain_desc->windowed = present_parameters->Windowed;
302  swapchain_desc->enable_auto_depth_stencil = present_parameters->EnableAutoDepthStencil;
303  swapchain_desc->auto_depth_stencil_format
305  swapchain_desc->flags
307  swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz;
308  swapchain_desc->swap_interval = present_parameters->PresentationInterval;
309  swapchain_desc->auto_restore_display_mode = TRUE;
310 
311  if (present_parameters->Flags & ~D3DPRESENTFLAGS_MASK)
312  FIXME("Unhandled flags %#x.\n", present_parameters->Flags & ~D3DPRESENTFLAGS_MASK);
313 
314  return TRUE;
315 }
316 
317 void d3dcaps_from_wined3dcaps(D3DCAPS9 *caps, const WINED3DCAPS *wined3d_caps)
318 {
319  static const DWORD ps_minor_version[] = {0, 4, 0, 0};
320  static const DWORD vs_minor_version[] = {0, 1, 0, 0};
321  static const DWORD texture_filter_caps =
327 
328  caps->DeviceType = (D3DDEVTYPE)wined3d_caps->DeviceType;
329  caps->AdapterOrdinal = wined3d_caps->AdapterOrdinal;
330  caps->Caps = wined3d_caps->Caps;
331  caps->Caps2 = wined3d_caps->Caps2;
332  caps->Caps3 = wined3d_caps->Caps3;
333  caps->PresentationIntervals = wined3d_caps->PresentationIntervals;
334  caps->CursorCaps = wined3d_caps->CursorCaps;
335  caps->DevCaps = wined3d_caps->DevCaps;
336  caps->PrimitiveMiscCaps = wined3d_caps->PrimitiveMiscCaps;
337  caps->RasterCaps = wined3d_caps->RasterCaps;
338  caps->ZCmpCaps = wined3d_caps->ZCmpCaps;
339  caps->SrcBlendCaps = wined3d_caps->SrcBlendCaps;
340  caps->DestBlendCaps = wined3d_caps->DestBlendCaps;
341  caps->AlphaCmpCaps = wined3d_caps->AlphaCmpCaps;
342  caps->ShadeCaps = wined3d_caps->ShadeCaps;
343  caps->TextureCaps = wined3d_caps->TextureCaps;
344  caps->TextureFilterCaps = wined3d_caps->TextureFilterCaps;
345  caps->CubeTextureFilterCaps = wined3d_caps->CubeTextureFilterCaps;
346  caps->VolumeTextureFilterCaps = wined3d_caps->VolumeTextureFilterCaps;
347  caps->TextureAddressCaps = wined3d_caps->TextureAddressCaps;
349  caps->LineCaps = wined3d_caps->LineCaps;
350  caps->MaxTextureWidth = wined3d_caps->MaxTextureWidth;
351  caps->MaxTextureHeight = wined3d_caps->MaxTextureHeight;
352  caps->MaxVolumeExtent = wined3d_caps->MaxVolumeExtent;
353  caps->MaxTextureRepeat = wined3d_caps->MaxTextureRepeat;
354  caps->MaxTextureAspectRatio = wined3d_caps->MaxTextureAspectRatio;
355  caps->MaxAnisotropy = wined3d_caps->MaxAnisotropy;
356  caps->MaxVertexW = wined3d_caps->MaxVertexW;
357  caps->GuardBandLeft = wined3d_caps->GuardBandLeft;
358  caps->GuardBandTop = wined3d_caps->GuardBandTop;
359  caps->GuardBandRight = wined3d_caps->GuardBandRight;
360  caps->GuardBandBottom = wined3d_caps->GuardBandBottom;
361  caps->ExtentsAdjust = wined3d_caps->ExtentsAdjust;
362  caps->StencilCaps = wined3d_caps->StencilCaps;
363  caps->FVFCaps = wined3d_caps->FVFCaps;
364  caps->TextureOpCaps = wined3d_caps->TextureOpCaps;
365  caps->MaxTextureBlendStages = wined3d_caps->MaxTextureBlendStages;
366  caps->MaxSimultaneousTextures = wined3d_caps->MaxSimultaneousTextures;
367  caps->VertexProcessingCaps = wined3d_caps->VertexProcessingCaps;
368  caps->MaxActiveLights = wined3d_caps->MaxActiveLights;
369  caps->MaxUserClipPlanes = wined3d_caps->MaxUserClipPlanes;
370  caps->MaxVertexBlendMatrices = wined3d_caps->MaxVertexBlendMatrices;
372  caps->MaxPointSize = wined3d_caps->MaxPointSize;
373  caps->MaxPrimitiveCount = wined3d_caps->MaxPrimitiveCount;
374  caps->MaxVertexIndex = wined3d_caps->MaxVertexIndex;
375  caps->MaxStreams = wined3d_caps->MaxStreams;
376  caps->MaxStreamStride = wined3d_caps->MaxStreamStride;
377  caps->VertexShaderVersion = wined3d_caps->VertexShaderVersion;
378  caps->MaxVertexShaderConst = wined3d_caps->MaxVertexShaderConst;
379  caps->PixelShaderVersion = wined3d_caps->PixelShaderVersion;
380  caps->PixelShader1xMaxValue = wined3d_caps->PixelShader1xMaxValue;
381  caps->DevCaps2 = wined3d_caps->DevCaps2;
383  caps->MasterAdapterOrdinal = wined3d_caps->MasterAdapterOrdinal;
384  caps->AdapterOrdinalInGroup = wined3d_caps->AdapterOrdinalInGroup;
385  caps->NumberOfAdaptersInGroup = wined3d_caps->NumberOfAdaptersInGroup;
386  caps->DeclTypes = wined3d_caps->DeclTypes;
387  caps->NumSimultaneousRTs = wined3d_caps->NumSimultaneousRTs;
388  caps->StretchRectFilterCaps = wined3d_caps->StretchRectFilterCaps;
389  caps->VS20Caps.Caps = wined3d_caps->VS20Caps.caps;
390  caps->VS20Caps.DynamicFlowControlDepth = wined3d_caps->VS20Caps.dynamic_flow_control_depth;
391  caps->VS20Caps.NumTemps = wined3d_caps->VS20Caps.temp_count;
392  caps->VS20Caps.StaticFlowControlDepth = wined3d_caps->VS20Caps.static_flow_control_depth;
393  caps->PS20Caps.Caps = wined3d_caps->PS20Caps.caps;
394  caps->PS20Caps.DynamicFlowControlDepth = wined3d_caps->PS20Caps.dynamic_flow_control_depth;
395  caps->PS20Caps.NumTemps = wined3d_caps->PS20Caps.temp_count;
396  caps->PS20Caps.StaticFlowControlDepth = wined3d_caps->PS20Caps.static_flow_control_depth;
397  caps->PS20Caps.NumInstructionSlots = wined3d_caps->PS20Caps.instruction_slot_count;
398  caps->VertexTextureFilterCaps = wined3d_caps->VertexTextureFilterCaps;
403 
404  /* Some functionality is implemented in d3d9.dll, not wined3d.dll. Add the needed caps. */
406 
407  /* Filter wined3d caps. */
408  caps->TextureFilterCaps &= texture_filter_caps;
409  caps->CubeTextureFilterCaps &= texture_filter_caps;
410  caps->VolumeTextureFilterCaps &= texture_filter_caps;
411 
412  caps->DevCaps &=
420 
421  caps->ShadeCaps &=
424 
425  caps->RasterCaps &=
432 
433  caps->DevCaps2 &=
437 
438  caps->Caps2 &=
441 
442  caps->VertexProcessingCaps &=
446 
447  caps->TextureCaps &=
454 
457 
458  if (caps->PixelShaderVersion > 3)
459  {
460  caps->PixelShaderVersion = D3DPS_VERSION(3, 0);
461  }
462  else
463  {
465  caps->PixelShaderVersion = D3DPS_VERSION(major, ps_minor_version[major]);
466  }
467 
468  if (caps->VertexShaderVersion > 3)
469  {
470  caps->VertexShaderVersion = D3DVS_VERSION(3, 0);
471  }
472  else
473  {
475  caps->VertexShaderVersion = D3DVS_VERSION(major, vs_minor_version[major]);
476  }
477 }
478 
479 static HRESULT WINAPI d3d9_device_QueryInterface(IDirect3DDevice9Ex *iface, REFIID riid, void **out)
480 {
481  TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
482 
483  if (IsEqualGUID(riid, &IID_IDirect3DDevice9)
485  {
487  *out = iface;
488  return S_OK;
489  }
490 
491  if (IsEqualGUID(riid, &IID_IDirect3DDevice9Ex))
492  {
494 
495  /* Find out if the creating d3d9 interface was created with Direct3DCreate9Ex.
496  * It doesn't matter with which function the device was created. */
497  if (!device->d3d_parent->extended)
498  {
499  WARN("IDirect3D9 instance wasn't created with CreateDirect3D9Ex, returning E_NOINTERFACE.\n");
500  *out = NULL;
501  return E_NOINTERFACE;
502  }
503 
505  *out = iface;
506  return S_OK;
507  }
508 
509  WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
510 
511  *out = NULL;
512  return E_NOINTERFACE;
513 }
514 
515 static ULONG WINAPI d3d9_device_AddRef(IDirect3DDevice9Ex *iface)
516 {
519 
520  TRACE("%p increasing refcount to %u.\n", iface, refcount);
521 
522  return refcount;
523 }
524 
525 static ULONG WINAPI DECLSPEC_HOTPATCH d3d9_device_Release(IDirect3DDevice9Ex *iface)
526 {
528  ULONG refcount;
529 
530  if (device->in_destruction)
531  return 0;
532 
533  refcount = InterlockedDecrement(&device->refcount);
534 
535  TRACE("%p decreasing refcount to %u.\n", iface, refcount);
536 
537  if (!refcount)
538  {
539  unsigned i;
540  device->in_destruction = TRUE;
541 
543  for (i = 0; i < device->fvf_decl_count; ++i)
544  {
545  wined3d_vertex_declaration_decref(device->fvf_decls[i].decl);
546  }
547  heap_free(device->fvf_decls);
548 
549  if (device->vertex_buffer)
550  wined3d_buffer_decref(device->vertex_buffer);
551  if (device->index_buffer)
552  wined3d_buffer_decref(device->index_buffer);
553 
554  heap_free(device->implicit_swapchains);
555 
556  wined3d_device_uninit_3d(device->wined3d_device);
558  wined3d_device_decref(device->wined3d_device);
560 
561  IDirect3D9Ex_Release(&device->d3d_parent->IDirect3D9Ex_iface);
562 
563  heap_free(device);
564  }
565 
566  return refcount;
567 }
568 
569 static HRESULT WINAPI d3d9_device_TestCooperativeLevel(IDirect3DDevice9Ex *iface)
570 {
572 
573  TRACE("iface %p.\n", iface);
574 
575  TRACE("device state: %#x.\n", device->device_state);
576 
577  if (device->d3d_parent->extended)
578  return D3D_OK;
579 
580  switch (device->device_state)
581  {
582  default:
584  return D3D_OK;
586  return D3DERR_DEVICELOST;
588  return D3DERR_DEVICENOTRESET;
589  }
590 }
591 
592 static UINT WINAPI d3d9_device_GetAvailableTextureMem(IDirect3DDevice9Ex *iface)
593 {
595  UINT ret;
596 
597  TRACE("iface %p.\n", iface);
598 
602 
603  return ret;
604 }
605 
606 static HRESULT WINAPI d3d9_device_EvictManagedResources(IDirect3DDevice9Ex *iface)
607 {
609 
610  TRACE("iface %p.\n", iface);
611 
615 
616  return D3D_OK;
617 }
618 
619 static HRESULT WINAPI d3d9_device_GetDirect3D(IDirect3DDevice9Ex *iface, IDirect3D9 **d3d9)
620 {
622 
623  TRACE("iface %p, d3d9 %p.\n", iface, d3d9);
624 
625  if (!d3d9)
626  return D3DERR_INVALIDCALL;
627 
628  return IDirect3D9Ex_QueryInterface(&device->d3d_parent->IDirect3D9Ex_iface, &IID_IDirect3D9, (void **)d3d9);
629 }
630 
631 static HRESULT WINAPI d3d9_device_GetDeviceCaps(IDirect3DDevice9Ex *iface, D3DCAPS9 *caps)
632 {
634  WINED3DCAPS wined3d_caps;
635  HRESULT hr;
636 
637  TRACE("iface %p, caps %p.\n", iface, caps);
638 
639  if (!caps)
640  return D3DERR_INVALIDCALL;
641 
642  memset(caps, 0, sizeof(*caps));
643 
645  hr = wined3d_device_get_device_caps(device->wined3d_device, &wined3d_caps);
647 
648  d3dcaps_from_wined3dcaps(caps, &wined3d_caps);
649 
650  return hr;
651 }
652 
653 static HRESULT WINAPI d3d9_device_GetDisplayMode(IDirect3DDevice9Ex *iface, UINT swapchain, D3DDISPLAYMODE *mode)
654 {
656  struct wined3d_display_mode wined3d_mode;
657  HRESULT hr;
658 
659  TRACE("iface %p, swapchain %u, mode %p.\n", iface, swapchain, mode);
660 
662  hr = wined3d_device_get_display_mode(device->wined3d_device, swapchain, &wined3d_mode, NULL);
664 
665  if (SUCCEEDED(hr))
666  {
667  mode->Width = wined3d_mode.width;
668  mode->Height = wined3d_mode.height;
669  mode->RefreshRate = wined3d_mode.refresh_rate;
670  mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
671  }
672 
673  return hr;
674 }
675 
676 static HRESULT WINAPI d3d9_device_GetCreationParameters(IDirect3DDevice9Ex *iface,
677  D3DDEVICE_CREATION_PARAMETERS *parameters)
678 {
680 
681  TRACE("iface %p, parameters %p.\n", iface, parameters);
682 
685  (struct wined3d_device_creation_parameters *)parameters);
687 
688  return D3D_OK;
689 }
690 
691 static HRESULT WINAPI d3d9_device_SetCursorProperties(IDirect3DDevice9Ex *iface,
692  UINT hotspot_x, UINT hotspot_y, IDirect3DSurface9 *bitmap)
693 {
696  HRESULT hr;
697 
698  TRACE("iface %p, hotspot_x %u, hotspot_y %u, bitmap %p.\n",
699  iface, hotspot_x, hotspot_y, bitmap);
700 
701  if (!bitmap)
702  {
703  WARN("No cursor bitmap, returning D3DERR_INVALIDCALL.\n");
704  return D3DERR_INVALIDCALL;
705  }
706 
709  hotspot_x, hotspot_y, bitmap_impl->wined3d_texture, bitmap_impl->sub_resource_idx);
711 
712  return hr;
713 }
714 
715 static void WINAPI d3d9_device_SetCursorPosition(IDirect3DDevice9Ex *iface, int x, int y, DWORD flags)
716 {
718 
719  TRACE("iface %p, x %u, y %u, flags %#x.\n", iface, x, y, flags);
720 
722  wined3d_device_set_cursor_position(device->wined3d_device, x, y, flags);
724 }
725 
726 static BOOL WINAPI d3d9_device_ShowCursor(IDirect3DDevice9Ex *iface, BOOL show)
727 {
729  BOOL ret;
730 
731  TRACE("iface %p, show %#x.\n", iface, show);
732 
734  ret = wined3d_device_show_cursor(device->wined3d_device, show);
736 
737  return ret;
738 }
739 
741  D3DPRESENT_PARAMETERS *present_parameters, IDirect3DSwapChain9 **swapchain)
742 {
745  struct d3d9_swapchain *object;
746  UINT i, count;
747  HRESULT hr;
748 
749  TRACE("iface %p, present_parameters %p, swapchain %p.\n",
750  iface, present_parameters, swapchain);
751 
752  if (!present_parameters->Windowed)
753  {
754  WARN("Trying to create an additional fullscreen swapchain, returning D3DERR_INVALIDCALL.\n");
755  return D3DERR_INVALIDCALL;
756  }
757 
760  for (i = 0; i < count; ++i)
761  {
763 
766 
767  if (!desc.windowed)
768  {
770  WARN("Trying to create an additional swapchain in fullscreen mode, returning D3DERR_INVALIDCALL.\n");
771  return D3DERR_INVALIDCALL;
772  }
773  }
775 
776  if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters,
777  device->d3d_parent->extended))
778  return D3DERR_INVALIDCALL;
779  if (SUCCEEDED(hr = d3d9_swapchain_create(device, &desc, &object)))
780  *swapchain = (IDirect3DSwapChain9 *)&object->IDirect3DSwapChain9Ex_iface;
782 
783  return hr;
784 }
785 
786 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_GetSwapChain(IDirect3DDevice9Ex *iface,
787  UINT swapchain_idx, IDirect3DSwapChain9 **swapchain)
788 {
790  HRESULT hr;
791 
792  TRACE("iface %p, swapchain_idx %u, swapchain %p.\n", iface, swapchain_idx, swapchain);
793 
795  if (swapchain_idx < device->implicit_swapchain_count)
796  {
797  *swapchain = (IDirect3DSwapChain9 *)&device->implicit_swapchains[swapchain_idx]->IDirect3DSwapChain9Ex_iface;
798  IDirect3DSwapChain9Ex_AddRef(*swapchain);
799  hr = D3D_OK;
800  }
801  else
802  {
803  *swapchain = NULL;
805  }
807 
808  return hr;
809 }
810 
811 static UINT WINAPI d3d9_device_GetNumberOfSwapChains(IDirect3DDevice9Ex *iface)
812 {
814  UINT count;
815 
816  TRACE("iface %p.\n", iface);
817 
821 
822  return count;
823 }
824 
826 {
828  IDirect3DBaseTexture9 *texture;
829  struct d3d9_surface *surface;
830  IUnknown *parent;
831 
833  if (desc.access & WINED3D_RESOURCE_ACCESS_CPU)
834  return D3D_OK;
835 
836  if (desc.resource_type != WINED3D_RTYPE_TEXTURE_2D)
837  {
838  WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource);
839  return D3DERR_INVALIDCALL;
840  }
841 
843  if (parent && SUCCEEDED(IUnknown_QueryInterface(parent, &IID_IDirect3DBaseTexture9, (void **)&texture)))
844  {
846  WARN("Texture %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", texture, resource);
847  return D3DERR_INVALIDCALL;
848  }
849 
851  if (!surface->resource.refcount)
852  return D3D_OK;
853 
854  WARN("Surface %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", surface);
855  return D3DERR_INVALIDCALL;
856 }
857 
859 {
860  UINT i, new_swapchain_count = wined3d_device_get_swapchain_count(device->wined3d_device);
862 
863  if (!(device->implicit_swapchains = heap_alloc(new_swapchain_count * sizeof(*device->implicit_swapchains))))
864  return E_OUTOFMEMORY;
865 
866  for (i = 0; i < new_swapchain_count; ++i)
867  {
869  device->implicit_swapchains[i] = wined3d_swapchain_get_parent(wined3d_swapchain);
870  }
871  device->implicit_swapchain_count = new_swapchain_count;
872 
873  return D3D_OK;
874 }
875 
877  D3DPRESENT_PARAMETERS *present_parameters, D3DDISPLAYMODEEX *mode)
878 {
879  BOOL extended = device->d3d_parent->extended;
880  struct wined3d_swapchain_desc swapchain_desc;
881  struct wined3d_display_mode wined3d_mode;
882  struct wined3d_rendertarget_view *rtv;
883  unsigned int i;
884  HRESULT hr;
885 
886  if (!extended && device->device_state == D3D9_DEVICE_STATE_LOST)
887  {
888  WARN("App not active, returning D3DERR_DEVICELOST.\n");
889  return D3DERR_DEVICELOST;
890  }
891 
892  if (mode)
893  {
894  wined3d_mode.width = mode->Width;
895  wined3d_mode.height = mode->Height;
896  wined3d_mode.refresh_rate = mode->RefreshRate;
897  wined3d_mode.format_id = wined3dformat_from_d3dformat(mode->Format);
898  wined3d_mode.scanline_ordering = mode->ScanLineOrdering;
899  }
900 
901  if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters, extended))
902  return D3DERR_INVALIDCALL;
903 
905 
906  if (device->vertex_buffer)
907  {
908  wined3d_buffer_decref(device->vertex_buffer);
909  device->vertex_buffer = NULL;
910  device->vertex_buffer_size = 0;
911  }
912 
913  if (device->index_buffer)
914  {
915  wined3d_buffer_decref(device->index_buffer);
916  device->index_buffer = NULL;
917  device->index_buffer_size = 0;
918  }
919 
920  if (SUCCEEDED(hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc,
921  mode ? &wined3d_mode : NULL, reset_enum_callback, !extended)))
922  {
923  heap_free(device->implicit_swapchains);
924 
925  if (!extended)
926  {
928  !!swapchain_desc.enable_auto_depth_stencil);
929  }
930 
932  {
933  device->device_state = D3D9_DEVICE_STATE_NOT_RESET;
934  }
935  else
936  {
937  wined3d_swapchain_get_desc(device->implicit_swapchains[0]->wined3d_swapchain, &swapchain_desc);
938  present_parameters->BackBufferWidth = swapchain_desc.backbuffer_width;
939  present_parameters->BackBufferHeight = swapchain_desc.backbuffer_height;
940  present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc.backbuffer_format);
941  present_parameters->BackBufferCount = swapchain_desc.backbuffer_count;
942 
943  device->device_state = D3D9_DEVICE_STATE_OK;
944  }
945 
946  if (!device->d3d_parent->extended)
947  for (i = 0; i < ARRAY_SIZE(device->textures); ++i)
948  device->textures[i] = NULL;
949 
950  rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0);
952  for (i = 1; i < ARRAY_SIZE(device->render_targets); ++i)
953  device->render_targets[i] = NULL;
954  }
955  else if (!extended)
956  {
957  device->device_state = D3D9_DEVICE_STATE_NOT_RESET;
958  }
959 
961 
962  return hr;
963 }
964 
965 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Reset(IDirect3DDevice9Ex *iface,
966  D3DPRESENT_PARAMETERS *present_parameters)
967 {
969 
970  TRACE("iface %p, present_parameters %p.\n", iface, present_parameters);
971 
972  return d3d9_device_reset(device, present_parameters, NULL);
973 }
974 
975 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex *iface,
976  const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region)
977 {
979  UINT i;
980  HRESULT hr;
981 
982  TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p.\n",
983  iface, src_rect, dst_rect, dst_window_override, dirty_region);
984 
985  if (device->device_state != D3D9_DEVICE_STATE_OK)
986  return device->d3d_parent->extended ? S_PRESENT_OCCLUDED : D3DERR_DEVICELOST;
987 
988  if (dirty_region)
989  FIXME("Ignoring dirty_region %p.\n", dirty_region);
990 
992  for (i = 0; i < device->implicit_swapchain_count; ++i)
993  {
994  if (FAILED(hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain,
995  src_rect, dst_rect, dst_window_override, 0, 0)))
996  {
998  return hr;
999  }
1000  }
1002 
1003  return D3D_OK;
1004 }
1005 
1006 static HRESULT WINAPI d3d9_device_GetBackBuffer(IDirect3DDevice9Ex *iface, UINT swapchain,
1007  UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface9 **backbuffer)
1008 {
1010  HRESULT hr;
1011 
1012  TRACE("iface %p, swapchain %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
1013  iface, swapchain, backbuffer_idx, backbuffer_type, backbuffer);
1014 
1015  /* backbuffer_type is ignored by native. */
1016 
1017  /* No need to check for backbuffer == NULL, Windows crashes in that case. */
1018  *backbuffer = NULL;
1019 
1021  if (swapchain >= device->implicit_swapchain_count)
1022  {
1024  WARN("Swapchain index %u is out of range, returning D3DERR_INVALIDCALL.\n", swapchain);
1025  return D3DERR_INVALIDCALL;
1026  }
1027 
1028  hr = IDirect3DSwapChain9Ex_GetBackBuffer(&device->implicit_swapchains[swapchain]->IDirect3DSwapChain9Ex_iface,
1029  backbuffer_idx, backbuffer_type, backbuffer);
1031 
1032  return hr;
1033 }
1034 
1035 static HRESULT WINAPI d3d9_device_GetRasterStatus(IDirect3DDevice9Ex *iface,
1036  UINT swapchain, D3DRASTER_STATUS *raster_status)
1037 {
1039  HRESULT hr;
1040 
1041  TRACE("iface %p, swapchain %u, raster_status %p.\n", iface, swapchain, raster_status);
1042 
1044  hr = wined3d_device_get_raster_status(device->wined3d_device,
1045  swapchain, (struct wined3d_raster_status *)raster_status);
1047 
1048  return hr;
1049 }
1050 
1051 static HRESULT WINAPI d3d9_device_SetDialogBoxMode(IDirect3DDevice9Ex *iface, BOOL enable)
1052 {
1054  HRESULT hr;
1055 
1056  TRACE("iface %p, enable %#x.\n", iface, enable);
1057 
1059  hr = wined3d_device_set_dialog_box_mode(device->wined3d_device, enable);
1061 
1062  return hr;
1063 }
1064 
1065 static void WINAPI d3d9_device_SetGammaRamp(IDirect3DDevice9Ex *iface,
1066  UINT swapchain, DWORD flags, const D3DGAMMARAMP *ramp)
1067 {
1069 
1070  TRACE("iface %p, swapchain %u, flags %#x, ramp %p.\n", iface, swapchain, flags, ramp);
1071 
1072  /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
1074  wined3d_device_set_gamma_ramp(device->wined3d_device, swapchain, flags, (const struct wined3d_gamma_ramp *)ramp);
1076 }
1077 
1078 static void WINAPI d3d9_device_GetGammaRamp(IDirect3DDevice9Ex *iface, UINT swapchain, D3DGAMMARAMP *ramp)
1079 {
1081 
1082  TRACE("iface %p, swapchain %u, ramp %p.\n", iface, swapchain, ramp);
1083 
1084  /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
1086  wined3d_device_get_gamma_ramp(device->wined3d_device, swapchain, (struct wined3d_gamma_ramp *)ramp);
1088 }
1089 
1090 static HRESULT WINAPI d3d9_device_CreateTexture(IDirect3DDevice9Ex *iface,
1092  D3DPOOL pool, IDirect3DTexture9 **texture, HANDLE *shared_handle)
1093 {
1095  struct d3d9_texture *object;
1096  BOOL set_mem = FALSE;
1097  HRESULT hr;
1098 
1099  TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
1100  iface, width, height, levels, usage, format, pool, texture, shared_handle);
1101 
1102  *texture = NULL;
1103  if (shared_handle)
1104  {
1105  if (!device->d3d_parent->extended)
1106  {
1107  WARN("Trying to create a shared or user memory texture on a non-ex device.\n");
1108  return E_NOTIMPL;
1109  }
1110 
1111  if (pool == D3DPOOL_SYSTEMMEM)
1112  {
1113  if (levels != 1)
1114  return D3DERR_INVALIDCALL;
1115  set_mem = TRUE;
1116  }
1117  else
1118  {
1119  if (pool != D3DPOOL_DEFAULT)
1120  {
1121  WARN("Trying to create a shared texture in pool %#x.\n", pool);
1122  return D3DERR_INVALIDCALL;
1123  }
1124  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1125  }
1126  }
1127 
1128  if (!(object = heap_alloc_zero(sizeof(*object))))
1129  return D3DERR_OUTOFVIDEOMEMORY;
1130 
1132  if (FAILED(hr))
1133  {
1134  WARN("Failed to initialize texture, hr %#x.\n", hr);
1135  heap_free(object);
1136  return hr;
1137  }
1138 
1139  if (set_mem)
1140  wined3d_texture_update_desc(object->wined3d_texture, width, height,
1142  *shared_handle, 0);
1143 
1144  TRACE("Created texture %p.\n", object);
1145  *texture = (IDirect3DTexture9 *)&object->IDirect3DBaseTexture9_iface;
1146 
1147  return D3D_OK;
1148 }
1149 
1150 static HRESULT WINAPI d3d9_device_CreateVolumeTexture(IDirect3DDevice9Ex *iface,
1152  D3DPOOL pool, IDirect3DVolumeTexture9 **texture, HANDLE *shared_handle)
1153 {
1155  struct d3d9_texture *object;
1156  HRESULT hr;
1157 
1158  TRACE("iface %p, width %u, height %u, depth %u, levels %u, "
1159  "usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
1160  iface, width, height, depth, levels,
1161  usage, format, pool, texture, shared_handle);
1162 
1163  *texture = NULL;
1164  if (shared_handle)
1165  {
1166  if (!device->d3d_parent->extended)
1167  {
1168  WARN("Trying to create a shared volume texture on a non-ex device.\n");
1169  return E_NOTIMPL;
1170  }
1171 
1172  if (pool != D3DPOOL_DEFAULT)
1173  {
1174  WARN("Trying to create a shared volume texture in pool %#x.\n", pool);
1175  return D3DERR_INVALIDCALL;
1176  }
1177  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1178  }
1179 
1180  if (!(object = heap_alloc_zero(sizeof(*object))))
1181  return D3DERR_OUTOFVIDEOMEMORY;
1182 
1184  if (FAILED(hr))
1185  {
1186  WARN("Failed to initialize volume texture, hr %#x.\n", hr);
1187  heap_free(object);
1188  return hr;
1189  }
1190 
1191  TRACE("Created volume texture %p.\n", object);
1192  *texture = (IDirect3DVolumeTexture9 *)&object->IDirect3DBaseTexture9_iface;
1193 
1194  return D3D_OK;
1195 }
1196 
1197 static HRESULT WINAPI d3d9_device_CreateCubeTexture(IDirect3DDevice9Ex *iface,
1199  IDirect3DCubeTexture9 **texture, HANDLE *shared_handle)
1200 {
1202  struct d3d9_texture *object;
1203  HRESULT hr;
1204 
1205  TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
1206  iface, edge_length, levels, usage, format, pool, texture, shared_handle);
1207 
1208  *texture = NULL;
1209  if (shared_handle)
1210  {
1211  if (!device->d3d_parent->extended)
1212  {
1213  WARN("Trying to create a shared cube texture on a non-ex device.\n");
1214  return E_NOTIMPL;
1215  }
1216 
1217  if (pool != D3DPOOL_DEFAULT)
1218  {
1219  WARN("Trying to create a shared cube texture in pool %#x.\n", pool);
1220  return D3DERR_INVALIDCALL;
1221  }
1222  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1223  }
1224 
1225  if (!(object = heap_alloc_zero(sizeof(*object))))
1226  return D3DERR_OUTOFVIDEOMEMORY;
1227 
1228  hr = cubetexture_init(object, device, edge_length, levels, usage, format, pool);
1229  if (FAILED(hr))
1230  {
1231  WARN("Failed to initialize cube texture, hr %#x.\n", hr);
1232  heap_free(object);
1233  return hr;
1234  }
1235 
1236  TRACE("Created cube texture %p.\n", object);
1237  *texture = (IDirect3DCubeTexture9 *)&object->IDirect3DBaseTexture9_iface;
1238 
1239  return D3D_OK;
1240 }
1241 
1242 static HRESULT WINAPI d3d9_device_CreateVertexBuffer(IDirect3DDevice9Ex *iface, UINT size,
1243  DWORD usage, DWORD fvf, D3DPOOL pool, IDirect3DVertexBuffer9 **buffer,
1244  HANDLE *shared_handle)
1245 {
1247  struct d3d9_vertexbuffer *object;
1248  HRESULT hr;
1249 
1250  TRACE("iface %p, size %u, usage %#x, fvf %#x, pool %#x, buffer %p, shared_handle %p.\n",
1251  iface, size, usage, fvf, pool, buffer, shared_handle);
1252 
1253  if (shared_handle)
1254  {
1255  if (!device->d3d_parent->extended)
1256  {
1257  WARN("Trying to create a shared vertex buffer on a non-ex device.\n");
1258  return E_NOTIMPL;
1259  }
1260 
1261  if (pool != D3DPOOL_DEFAULT)
1262  {
1263  WARN("Trying to create a shared vertex buffer in pool %#x.\n", pool);
1264  return D3DERR_NOTAVAILABLE;
1265  }
1266  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1267  }
1268 
1269  if (!(object = heap_alloc_zero(sizeof(*object))))
1270  return D3DERR_OUTOFVIDEOMEMORY;
1271 
1272  hr = vertexbuffer_init(object, device, size, usage, fvf, pool);
1273  if (FAILED(hr))
1274  {
1275  WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
1276  heap_free(object);
1277  return hr;
1278  }
1279 
1280  TRACE("Created vertex buffer %p.\n", object);
1281  *buffer = &object->IDirect3DVertexBuffer9_iface;
1282 
1283  return D3D_OK;
1284 }
1285 
1286 static HRESULT WINAPI d3d9_device_CreateIndexBuffer(IDirect3DDevice9Ex *iface, UINT size,
1287  DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer9 **buffer,
1288  HANDLE *shared_handle)
1289 {
1291  struct d3d9_indexbuffer *object;
1292  HRESULT hr;
1293 
1294  TRACE("iface %p, size %u, usage %#x, format %#x, pool %#x, buffer %p, shared_handle %p.\n",
1295  iface, size, usage, format, pool, buffer, shared_handle);
1296 
1297  if (shared_handle)
1298  {
1299  if (!device->d3d_parent->extended)
1300  {
1301  WARN("Trying to create a shared index buffer on a non-ex device.\n");
1302  return E_NOTIMPL;
1303  }
1304 
1305  if (pool != D3DPOOL_DEFAULT)
1306  {
1307  WARN("Trying to create a shared index buffer in pool %#x.\n", pool);
1308  return D3DERR_NOTAVAILABLE;
1309  }
1310  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1311  }
1312 
1313  if (!(object = heap_alloc_zero(sizeof(*object))))
1314  return D3DERR_OUTOFVIDEOMEMORY;
1315 
1316  hr = indexbuffer_init(object, device, size, usage, format, pool);
1317  if (FAILED(hr))
1318  {
1319  WARN("Failed to initialize index buffer, hr %#x.\n", hr);
1320  heap_free(object);
1321  return hr;
1322  }
1323 
1324  TRACE("Created index buffer %p.\n", object);
1325  *buffer = &object->IDirect3DIndexBuffer9_iface;
1326 
1327  return D3D_OK;
1328 }
1329 
1331  D3DFORMAT format, DWORD flags, IDirect3DSurface9 **surface, UINT usage, D3DPOOL pool,
1332  D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, void *user_mem)
1333 {
1334  struct wined3d_resource_desc desc;
1335  struct d3d9_surface *surface_impl;
1336  struct wined3d_texture *texture;
1337  HRESULT hr;
1338 
1339  TRACE("device %p, width %u, height %u, format %#x, flags %#x, surface %p.\n"
1340  "usage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n",
1341  device, width, height, format, flags, surface, usage, pool,
1342  multisample_type, multisample_quality);
1343 
1344  desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
1346  desc.multisample_type = multisample_type;
1347  desc.multisample_quality = multisample_quality;
1348  desc.usage = usage & WINED3DUSAGE_MASK;
1349  if (pool == D3DPOOL_SCRATCH)
1350  desc.usage |= WINED3DUSAGE_SCRATCH;
1353  desc.width = width;
1354  desc.height = height;
1355  desc.depth = 1;
1356  desc.size = 0;
1357 
1358  if (is_gdi_compat_wined3dformat(desc.format))
1360 
1362 
1363  if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &desc,
1365  {
1367  WARN("Failed to create texture, hr %#x.\n", hr);
1368  if (hr == WINED3DERR_NOTAVAILABLE)
1370  return hr;
1371  }
1372 
1374  surface_impl->parent_device = &device->IDirect3DDevice9Ex_iface;
1375  *surface = &surface_impl->IDirect3DSurface9_iface;
1376  IDirect3DSurface9_AddRef(*surface);
1377 
1378  if (user_mem)
1380  desc.format, multisample_type, multisample_quality, user_mem, 0);
1381 
1383 
1385 
1386  return D3D_OK;
1387 }
1388 
1390 {
1391  switch (format)
1392  {
1399  return TRUE;
1400  default:
1401  return FALSE;
1402  }
1403 }
1404 
1406  D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
1407  BOOL lockable, IDirect3DSurface9 **surface, HANDLE *shared_handle)
1408 {
1410  DWORD flags = 0;
1411 
1412  TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
1413  "lockable %#x, surface %p, shared_handle %p.\n",
1414  iface, width, height, format, multisample_type, multisample_quality,
1415  lockable, surface, shared_handle);
1416 
1417  *surface = NULL;
1418  if (shared_handle)
1419  {
1420  if (!device->d3d_parent->extended)
1421  {
1422  WARN("Trying to create a shared render target on a non-ex device.\n");
1423  return E_NOTIMPL;
1424  }
1425 
1426  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1427  }
1428 
1429  if (lockable)
1431 
1433  D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL);
1434 }
1435 
1437  D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
1438  BOOL discard, IDirect3DSurface9 **surface, HANDLE *shared_handle)
1439 {
1442 
1443  TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
1444  "discard %#x, surface %p, shared_handle %p.\n",
1445  iface, width, height, format, multisample_type, multisample_quality,
1446  discard, surface, shared_handle);
1447 
1448  *surface = NULL;
1449  if (shared_handle)
1450  {
1451  if (!device->d3d_parent->extended)
1452  {
1453  WARN("Trying to create a shared depth stencil on a non-ex device.\n");
1454  return E_NOTIMPL;
1455  }
1456 
1457  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1458  }
1459 
1460  if (discard)
1462 
1464  D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL);
1465 }
1466 
1467 
1468 static HRESULT WINAPI d3d9_device_UpdateSurface(IDirect3DDevice9Ex *iface,
1469  IDirect3DSurface9 *src_surface, const RECT *src_rect,
1470  IDirect3DSurface9 *dst_surface, const POINT *dst_point)
1471 {
1473  struct d3d9_surface *src = unsafe_impl_from_IDirect3DSurface9(src_surface);
1474  struct d3d9_surface *dst = unsafe_impl_from_IDirect3DSurface9(dst_surface);
1475  struct wined3d_sub_resource_desc src_desc, dst_desc;
1476  struct wined3d_box src_box;
1477  HRESULT hr;
1478 
1479  TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_point %p.\n",
1480  iface, src_surface, src_rect, dst_surface, dst_point);
1481 
1483 
1484  wined3d_texture_get_sub_resource_desc(src->wined3d_texture, src->sub_resource_idx, &src_desc);
1485  wined3d_texture_get_sub_resource_desc(dst->wined3d_texture, dst->sub_resource_idx, &dst_desc);
1486  if (src_desc.format != dst_desc.format)
1487  {
1489  WARN("Surface formats (%#x/%#x) don't match.\n",
1492  return D3DERR_INVALIDCALL;
1493  }
1494 
1495  if (src_rect)
1496  wined3d_box_set(&src_box, src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1);
1497  else
1498  wined3d_box_set(&src_box, 0, 0, src_desc.width, src_desc.height, 0, 1);
1499 
1501  wined3d_texture_get_resource(dst->wined3d_texture), dst->sub_resource_idx, dst_point ? dst_point->x : 0,
1502  dst_point ? dst_point->y : 0, 0, wined3d_texture_get_resource(src->wined3d_texture),
1503  src->sub_resource_idx, &src_box);
1504  if (SUCCEEDED(hr) && dst->texture)
1506 
1508 
1509  if (FAILED(hr))
1510  return D3DERR_INVALIDCALL;
1511 
1512  return hr;
1513 }
1514 
1515 static HRESULT WINAPI d3d9_device_UpdateTexture(IDirect3DDevice9Ex *iface,
1516  IDirect3DBaseTexture9 *src_texture, IDirect3DBaseTexture9 *dst_texture)
1517 {
1519  struct d3d9_texture *src_impl, *dst_impl;
1520  HRESULT hr;
1521 
1522  TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
1523 
1524  src_impl = unsafe_impl_from_IDirect3DBaseTexture9(src_texture);
1525  dst_impl = unsafe_impl_from_IDirect3DBaseTexture9(dst_texture);
1526 
1528  hr = wined3d_device_update_texture(device->wined3d_device,
1529  src_impl->wined3d_texture, dst_impl->wined3d_texture);
1530  if (SUCCEEDED(hr))
1533 
1534  return hr;
1535 }
1536 
1537 static HRESULT WINAPI d3d9_device_GetRenderTargetData(IDirect3DDevice9Ex *iface,
1538  IDirect3DSurface9 *render_target, IDirect3DSurface9 *dst_surface)
1539 {
1540  struct d3d9_surface *rt_impl = unsafe_impl_from_IDirect3DSurface9(render_target);
1541  struct d3d9_surface *dst_impl = unsafe_impl_from_IDirect3DSurface9(dst_surface);
1542  struct wined3d_sub_resource_desc wined3d_desc;
1543  RECT dst_rect, src_rect;
1544  HRESULT hr;
1545 
1546  TRACE("iface %p, render_target %p, dst_surface %p.\n", iface, render_target, dst_surface);
1547 
1548  if (!render_target || !dst_surface)
1549  return D3DERR_INVALIDCALL;
1550 
1552  wined3d_texture_get_sub_resource_desc(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &wined3d_desc);
1553  SetRect(&dst_rect, 0, 0, wined3d_desc.width, wined3d_desc.height);
1554 
1555  wined3d_texture_get_sub_resource_desc(rt_impl->wined3d_texture, rt_impl->sub_resource_idx, &wined3d_desc);
1556  SetRect(&src_rect, 0, 0, wined3d_desc.width, wined3d_desc.height);
1557 
1558  /* TODO: Check surface sizes, pools, etc. */
1559  if (wined3d_desc.multisample_type)
1561  else
1562  hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect,
1563  rt_impl->wined3d_texture, rt_impl->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT);
1565 
1566  return hr;
1567 }
1568 
1569 static HRESULT WINAPI d3d9_device_GetFrontBufferData(IDirect3DDevice9Ex *iface,
1570  UINT swapchain, IDirect3DSurface9 *dst_surface)
1571 {
1573  struct d3d9_surface *dst_impl = unsafe_impl_from_IDirect3DSurface9(dst_surface);
1575 
1576  TRACE("iface %p, swapchain %u, dst_surface %p.\n", iface, swapchain, dst_surface);
1577 
1579  if (swapchain < device->implicit_swapchain_count)
1580  hr = wined3d_swapchain_get_front_buffer_data(device->implicit_swapchains[swapchain]->wined3d_swapchain,
1581  dst_impl->wined3d_texture, dst_impl->sub_resource_idx);
1583 
1584  return hr;
1585 }
1586 
1587 static HRESULT WINAPI d3d9_device_StretchRect(IDirect3DDevice9Ex *iface, IDirect3DSurface9 *src_surface,
1588  const RECT *src_rect, IDirect3DSurface9 *dst_surface, const RECT *dst_rect, D3DTEXTUREFILTERTYPE filter)
1589 {
1591  struct d3d9_surface *src = unsafe_impl_from_IDirect3DSurface9(src_surface);
1592  struct d3d9_surface *dst = unsafe_impl_from_IDirect3DSurface9(dst_surface);
1593  struct wined3d_sub_resource_desc src_desc, dst_desc;
1595  RECT d, s;
1596 
1597  TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %#x.\n",
1598  iface, src_surface, src_rect, dst_surface, dst_rect, filter);
1599 
1601  wined3d_texture_get_sub_resource_desc(dst->wined3d_texture, dst->sub_resource_idx, &dst_desc);
1602  if (!dst_rect)
1603  {
1604  SetRect(&d, 0, 0, dst_desc.width, dst_desc.height);
1605  dst_rect = &d;
1606  }
1607 
1608  wined3d_texture_get_sub_resource_desc(src->wined3d_texture, src->sub_resource_idx, &src_desc);
1609  if (!src_rect)
1610  {
1611  SetRect(&s, 0, 0, src_desc.width, src_desc.height);
1612  src_rect = &s;
1613  }
1614 
1615  if (dst_desc.access & WINED3D_RESOURCE_ACCESS_CPU)
1616  {
1617  WARN("Destination resource is not in DEFAULT pool.\n");
1618  goto done;
1619  }
1620  if (src_desc.access & WINED3D_RESOURCE_ACCESS_CPU)
1621  {
1622  WARN("Source resource is not in DEFAULT pool.\n");
1623  goto done;
1624  }
1625 
1626  if (dst->texture && !(dst_desc.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL)))
1627  {
1628  WARN("Destination is a regular texture.\n");
1629  goto done;
1630  }
1631 
1632  if (src_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
1633  {
1634  if (device->in_scene)
1635  {
1636  WARN("Rejecting depth / stencil blit while in scene.\n");
1637  goto done;
1638  }
1639 
1640  if (src_rect->left || src_rect->top || src_rect->right != src_desc.width
1641  || src_rect->bottom != src_desc.height)
1642  {
1643  WARN("Rejecting depth / stencil blit with invalid source rect %s.\n",
1644  wine_dbgstr_rect(src_rect));
1645  goto done;
1646  }
1647 
1648  if (dst_rect->left || dst_rect->top || dst_rect->right != dst_desc.width
1649  || dst_rect->bottom != dst_desc.height)
1650  {
1651  WARN("Rejecting depth / stencil blit with invalid destination rect %s.\n",
1652  wine_dbgstr_rect(dst_rect));
1653  goto done;
1654  }
1655 
1656  if (src_desc.width != dst_desc.width || src_desc.height != dst_desc.height)
1657  {
1658  WARN("Rejecting depth / stencil blit with mismatched surface sizes.\n");
1659  goto done;
1660  }
1661  }
1662 
1663  hr = wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, dst_rect,
1664  src->wined3d_texture, src->sub_resource_idx, src_rect, 0, NULL, filter);
1665  if (hr == WINEDDERR_INVALIDRECT)
1667  if (SUCCEEDED(hr) && dst->texture)
1669 
1670 done:
1672  return hr;
1673 }
1674 
1675 static HRESULT WINAPI d3d9_device_ColorFill(IDirect3DDevice9Ex *iface,
1676  IDirect3DSurface9 *surface, const RECT *rect, D3DCOLOR color)
1677 {
1678  const struct wined3d_color c =
1679  {
1680  ((color >> 16) & 0xff) / 255.0f,
1681  ((color >> 8) & 0xff) / 255.0f,
1682  (color & 0xff) / 255.0f,
1683  ((color >> 24) & 0xff) / 255.0f,
1684  };
1686  struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface);
1688  struct wined3d_rendertarget_view *rtv;
1689  HRESULT hr;
1690 
1691  TRACE("iface %p, surface %p, rect %p, color 0x%08x.\n", iface, surface, rect, color);
1692 
1694 
1696  surface_impl->sub_resource_idx, &desc)))
1697  {
1699  return D3DERR_INVALIDCALL;
1700  }
1701 
1702  if (desc.access & WINED3D_RESOURCE_ACCESS_CPU)
1703  {
1705  WARN("Colour fills are not allowed on surfaces with resource access %#x.\n", desc.access);
1706  return D3DERR_INVALIDCALL;
1707  }
1709  {
1711  WARN("Colorfill is not allowed on non-RT textures, returning D3DERR_INVALIDCALL.\n");
1712  return D3DERR_INVALIDCALL;
1713  }
1714  if (desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
1715  {
1717  WARN("Colorfill is not allowed on depth stencil surfaces, returning D3DERR_INVALIDCALL.\n");
1718  return D3DERR_INVALIDCALL;
1719  }
1720 
1721  rtv = d3d9_surface_acquire_rendertarget_view(surface_impl);
1723  rtv, rect, WINED3DCLEAR_TARGET, &c, 0.0f, 0);
1724  d3d9_surface_release_rendertarget_view(surface_impl, rtv);
1725  if (SUCCEEDED(hr) && surface_impl->texture)
1727 
1729 
1730  return hr;
1731 }
1732 
1733 static HRESULT WINAPI d3d9_device_CreateOffscreenPlainSurface(IDirect3DDevice9Ex *iface,
1734  UINT width, UINT height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface,
1735  HANDLE *shared_handle)
1736 {
1738  void *user_mem = NULL;
1739 
1740  TRACE("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p.\n",
1741  iface, width, height, format, pool, surface, shared_handle);
1742 
1743  *surface = NULL;
1744  if (pool == D3DPOOL_MANAGED)
1745  {
1746  WARN("Attempting to create a managed offscreen plain surface.\n");
1747  return D3DERR_INVALIDCALL;
1748  }
1749 
1750  if (shared_handle)
1751  {
1752  if (!device->d3d_parent->extended)
1753  {
1754  WARN("Trying to create a shared or user memory surface on a non-ex device.\n");
1755  return E_NOTIMPL;
1756  }
1757 
1758  if (pool == D3DPOOL_SYSTEMMEM)
1759  user_mem = *shared_handle;
1760  else
1761  {
1762  if (pool != D3DPOOL_DEFAULT)
1763  {
1764  WARN("Trying to create a shared surface in pool %#x.\n", pool);
1765  return D3DERR_INVALIDCALL;
1766  }
1767  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1768  }
1769  }
1770 
1771  /* FIXME: Offscreen surfaces are supposed to be always lockable,
1772  * regardless of the pool they're created in. Should we set dynamic usage
1773  * here? */
1775  WINED3D_TEXTURE_CREATE_MAPPABLE, surface, 0, pool, D3DMULTISAMPLE_NONE, 0, user_mem);
1776 }
1777 
1778 static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 *surface)
1779 {
1781  struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface);
1782  struct wined3d_rendertarget_view *rtv;
1783  HRESULT hr;
1784 
1785  TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface);
1786 
1788  {
1789  WARN("Invalid index %u specified.\n", idx);
1790  return D3DERR_INVALIDCALL;
1791  }
1792 
1793  if (!idx && !surface_impl)
1794  {
1795  WARN("Trying to set render target 0 to NULL.\n");
1796  return D3DERR_INVALIDCALL;
1797  }
1798 
1799  if (surface_impl && d3d9_surface_get_device(surface_impl) != device)
1800  {
1801  WARN("Render target surface does not match device.\n");
1802  return D3DERR_INVALIDCALL;
1803  }
1804 
1806  rtv = surface_impl ? d3d9_surface_acquire_rendertarget_view(surface_impl) : NULL;
1807  hr = wined3d_device_set_rendertarget_view(device->wined3d_device, idx, rtv, TRUE);
1808  d3d9_surface_release_rendertarget_view(surface_impl, rtv);
1809  if (SUCCEEDED(hr))
1810  device->render_targets[idx] = surface_impl;
1812 
1813  return hr;
1814 }
1815 
1816 static HRESULT WINAPI d3d9_device_GetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 **surface)
1817 {
1819  struct wined3d_rendertarget_view *wined3d_rtv;
1820  struct d3d9_surface *surface_impl;
1821  HRESULT hr = D3D_OK;
1822 
1823  TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface);
1824 
1825  if (!surface)
1826  return D3DERR_INVALIDCALL;
1827 
1829  {
1830  WARN("Invalid index %u specified.\n", idx);
1831  return D3DERR_INVALIDCALL;
1832  }
1833 
1835  if ((wined3d_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, idx)))
1836  {
1837  /* We want the sub resource parent here, since the view itself may be
1838  * internal to wined3d and may not have a parent. */
1840  *surface = &surface_impl->IDirect3DSurface9_iface;
1841  IDirect3DSurface9_AddRef(*surface);
1842  }
1843  else
1844  {
1845  hr = D3DERR_NOTFOUND;
1846  *surface = NULL;
1847  }
1849 
1850  return hr;
1851 }
1852 
1853 static HRESULT WINAPI d3d9_device_SetDepthStencilSurface(IDirect3DDevice9Ex *iface, IDirect3DSurface9 *depth_stencil)
1854 {
1856  struct d3d9_surface *ds_impl = unsafe_impl_from_IDirect3DSurface9(depth_stencil);
1857  struct wined3d_rendertarget_view *rtv;
1858 
1859  TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
1860 
1862  rtv = ds_impl ? d3d9_surface_acquire_rendertarget_view(ds_impl) : NULL;
1863  wined3d_device_set_depth_stencil_view(device->wined3d_device, rtv);
1866 
1867  return D3D_OK;
1868 }
1869 
1870 static HRESULT WINAPI d3d9_device_GetDepthStencilSurface(IDirect3DDevice9Ex *iface, IDirect3DSurface9 **depth_stencil)
1871 {
1873  struct wined3d_rendertarget_view *wined3d_dsv;
1874  struct d3d9_surface *surface_impl;
1875  HRESULT hr = D3D_OK;
1876 
1877  TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
1878 
1879  if (!depth_stencil)
1880  return D3DERR_INVALIDCALL;
1881 
1883  if ((wined3d_dsv = wined3d_device_get_depth_stencil_view(device->wined3d_device)))
1884  {
1885  /* We want the sub resource parent here, since the view itself may be
1886  * internal to wined3d and may not have a parent. */
1887  surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_dsv);
1888  *depth_stencil = &surface_impl->IDirect3DSurface9_iface;
1889  IDirect3DSurface9_AddRef(*depth_stencil);
1890  }
1891  else
1892  {
1893  hr = D3DERR_NOTFOUND;
1894  *depth_stencil = NULL;
1895  }
1897 
1898  return hr;
1899 }
1900 
1901 static HRESULT WINAPI d3d9_device_BeginScene(IDirect3DDevice9Ex *iface)
1902 {
1904  HRESULT hr;
1905 
1906  TRACE("iface %p.\n", iface);
1907 
1909  if (SUCCEEDED(hr = wined3d_device_begin_scene(device->wined3d_device)))
1910  device->in_scene = TRUE;
1912 
1913  return hr;
1914 }
1915 
1916 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_EndScene(IDirect3DDevice9Ex *iface)
1917 {
1919  HRESULT hr;
1920 
1921  TRACE("iface %p.\n", iface);
1922 
1924  if (SUCCEEDED(hr = wined3d_device_end_scene(device->wined3d_device)))
1925  device->in_scene = FALSE;
1927 
1928  return hr;
1929 }
1930 
1932 {
1933  unsigned int i;
1934 
1935  for (i = 0; i < ARRAY_SIZE(device->render_targets); ++i)
1936  {
1937  struct d3d9_surface *surface = device->render_targets[i];
1938 
1939  if (surface && surface->texture)
1941  }
1942 }
1943 
1944 static HRESULT WINAPI d3d9_device_Clear(IDirect3DDevice9Ex *iface, DWORD rect_count,
1945  const D3DRECT *rects, DWORD flags, D3DCOLOR color, float z, DWORD stencil)
1946 {
1947  const struct wined3d_color c =
1948  {
1949  ((color >> 16) & 0xff) / 255.0f,
1950  ((color >> 8) & 0xff) / 255.0f,
1951  (color & 0xff) / 255.0f,
1952  ((color >> 24) & 0xff) / 255.0f,
1953  };
1955  HRESULT hr;
1956 
1957  TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %u.\n",
1958  iface, rect_count, rects, flags, color, z, stencil);
1959 
1960  if (rect_count && !rects)
1961  {
1962  WARN("count %u with NULL rects.\n", rect_count);
1963  rect_count = 0;
1964  }
1965 
1967  hr = wined3d_device_clear(device->wined3d_device, rect_count, (const RECT *)rects, flags, &c, z, stencil);
1968  if (SUCCEEDED(hr))
1971 
1972  return hr;
1973 }
1974 
1975 static HRESULT WINAPI d3d9_device_SetTransform(IDirect3DDevice9Ex *iface,
1977 {
1979 
1980  TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
1981 
1982  /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1984  wined3d_device_set_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
1986 
1987  return D3D_OK;
1988 }
1989 
1990 static HRESULT WINAPI d3d9_device_GetTransform(IDirect3DDevice9Ex *iface,
1992 {
1994 
1995  TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
1996 
1997  /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1999  wined3d_device_get_transform(device->wined3d_device, state, (struct wined3d_matrix *)matrix);
2001 
2002  return D3D_OK;
2003 }
2004 
2005 static HRESULT WINAPI d3d9_device_MultiplyTransform(IDirect3DDevice9Ex *iface,
2007 {
2009 
2010  TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
2011 
2012  /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
2014  wined3d_device_multiply_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
2016 
2017  return D3D_OK;
2018 }
2019 
2020 static HRESULT WINAPI d3d9_device_SetViewport(IDirect3DDevice9Ex *iface, const D3DVIEWPORT9 *viewport)
2021 {
2023  struct wined3d_viewport vp;
2024 
2025  TRACE("iface %p, viewport %p.\n", iface, viewport);
2026 
2027  vp.x = viewport->X;
2028  vp.y = viewport->Y;
2029  vp.width = viewport->Width;
2030  vp.height = viewport->Height;
2031  vp.min_z = viewport->MinZ;
2032  vp.max_z = viewport->MaxZ;
2033 
2035  wined3d_device_set_viewport(device->wined3d_device, &vp);
2037 
2038  return D3D_OK;
2039 }
2040 
2041 static HRESULT WINAPI d3d9_device_GetViewport(IDirect3DDevice9Ex *iface, D3DVIEWPORT9 *viewport)
2042 {
2045 
2046  TRACE("iface %p, viewport %p.\n", iface, viewport);
2047 
2051 
2052  viewport->X = wined3d_viewport.x;
2053  viewport->Y = wined3d_viewport.y;
2054  viewport->Width = wined3d_viewport.width;
2055  viewport->Height = wined3d_viewport.height;
2056  viewport->MinZ = wined3d_viewport.min_z;
2057  viewport->MaxZ = wined3d_viewport.max_z;
2058 
2059  return D3D_OK;
2060 }
2061 
2062 static HRESULT WINAPI d3d9_device_SetMaterial(IDirect3DDevice9Ex *iface, const D3DMATERIAL9 *material)
2063 {
2065 
2066  TRACE("iface %p, material %p.\n", iface, material);
2067 
2068  /* Note: D3DMATERIAL9 is compatible with struct wined3d_material. */
2070  wined3d_device_set_material(device->wined3d_device, (const struct wined3d_material *)material);
2072 
2073  return D3D_OK;
2074 }
2075 
2076 static HRESULT WINAPI d3d9_device_GetMaterial(IDirect3DDevice9Ex *iface, D3DMATERIAL9 *material)
2077 {
2079 
2080  TRACE("iface %p, material %p.\n", iface, material);
2081 
2082  /* Note: D3DMATERIAL9 is compatible with struct wined3d_material. */
2084  wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
2086 
2087  return D3D_OK;
2088 }
2089 
2090 static HRESULT WINAPI d3d9_device_SetLight(IDirect3DDevice9Ex *iface, DWORD index, const D3DLIGHT9 *light)
2091 {
2093  HRESULT hr;
2094 
2095  TRACE("iface %p, index %u, light %p.\n", iface, index, light);
2096 
2097  /* Note: D3DLIGHT9 is compatible with struct wined3d_light. */
2099  hr = wined3d_device_set_light(device->wined3d_device, index, (const struct wined3d_light *)light);
2101 
2102  return hr;
2103 }
2104 
2105 static HRESULT WINAPI d3d9_device_GetLight(IDirect3DDevice9Ex *iface, DWORD index, D3DLIGHT9 *light)
2106 {
2108  HRESULT hr;
2109 
2110  TRACE("iface %p, index %u, light %p.\n", iface, index, light);
2111 
2112  /* Note: D3DLIGHT9 is compatible with struct wined3d_light. */
2114  hr = wined3d_device_get_light(device->wined3d_device, index, (struct wined3d_light *)light);
2116 
2117  return hr;
2118 }
2119 
2120 static HRESULT WINAPI d3d9_device_LightEnable(IDirect3DDevice9Ex *iface, DWORD index, BOOL enable)
2121 {
2123  HRESULT hr;
2124 
2125  TRACE("iface %p, index %u, enable %#x.\n", iface, index, enable);
2126 
2128  hr = wined3d_device_set_light_enable(device->wined3d_device, index, enable);
2130 
2131  return hr;
2132 }
2133 
2134 static HRESULT WINAPI d3d9_device_GetLightEnable(IDirect3DDevice9Ex *iface, DWORD index, BOOL *enable)
2135 {
2137  HRESULT hr;
2138 
2139  TRACE("iface %p, index %u, enable %p.\n", iface, index, enable);
2140 
2142  hr = wined3d_device_get_light_enable(device->wined3d_device, index, enable);
2144 
2145  return hr;
2146 }
2147 
2148 static HRESULT WINAPI d3d9_device_SetClipPlane(IDirect3DDevice9Ex *iface, DWORD index, const float *plane)
2149 {
2151  HRESULT hr;
2152 
2153  TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
2154 
2155  index = min(index, device->max_user_clip_planes - 1);
2156 
2158  hr = wined3d_device_set_clip_plane(device->wined3d_device, index, (const struct wined3d_vec4 *)plane);
2160 
2161  return hr;
2162 }
2163 
2164 static HRESULT WINAPI d3d9_device_GetClipPlane(IDirect3DDevice9Ex *iface, DWORD index, float *plane)
2165 {
2167  HRESULT hr;
2168 
2169  TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
2170 
2171  index = min(index, device->max_user_clip_planes - 1);
2172 
2174  hr = wined3d_device_get_clip_plane(device->wined3d_device, index, (struct wined3d_vec4 *)plane);
2176 
2177  return hr;
2178 }
2179 
2182 {
2184 
2185  TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2186 
2190 
2191  return D3D_OK;
2192 }
2193 
2194 static HRESULT WINAPI d3d9_device_GetRenderState(IDirect3DDevice9Ex *iface,
2196 {
2198 
2199  TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2200 
2202  *value = wined3d_device_get_render_state(device->wined3d_device, state);
2204 
2205  return D3D_OK;
2206 }
2207 
2208 static HRESULT WINAPI d3d9_device_CreateStateBlock(IDirect3DDevice9Ex *iface,
2209  D3DSTATEBLOCKTYPE type, IDirect3DStateBlock9 **stateblock)
2210 {
2212  struct d3d9_stateblock *object;
2213  HRESULT hr;
2214 
2215  TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
2216 
2218  {
2219  WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL.\n");
2220  return D3DERR_INVALIDCALL;
2221  }
2222 
2223  if (!(object = heap_alloc_zero(sizeof(*object))))
2224  return E_OUTOFMEMORY;
2225 
2226  hr = stateblock_init(object, device, type, NULL);
2227  if (FAILED(hr))
2228  {
2229  WARN("Failed to initialize stateblock, hr %#x.\n", hr);
2230  heap_free(object);
2231  return hr;
2232  }
2233 
2234  TRACE("Created stateblock %p.\n", object);
2235  *stateblock = &object->IDirect3DStateBlock9_iface;
2236 
2237  return D3D_OK;
2238 }
2239 
2240 static HRESULT WINAPI d3d9_device_BeginStateBlock(IDirect3DDevice9Ex *iface)
2241 {
2243  HRESULT hr;
2244 
2245  TRACE("iface %p.\n", iface);
2246 
2248  hr = wined3d_device_begin_stateblock(device->wined3d_device);
2250 
2251  return hr;
2252 }
2253 
2254 static HRESULT WINAPI d3d9_device_EndStateBlock(IDirect3DDevice9Ex *iface, IDirect3DStateBlock9 **stateblock)
2255 {
2258  struct d3d9_stateblock *object;
2259  HRESULT hr;
2260 
2261  TRACE("iface %p, stateblock %p.\n", iface, stateblock);
2262 
2266  if (FAILED(hr))
2267  {
2268  WARN("Failed to end the state block, hr %#x.\n", hr);
2269  return hr;
2270  }
2271 
2272  if (!(object = heap_alloc_zero(sizeof(*object))))
2273  {
2277  return E_OUTOFMEMORY;
2278  }
2279 
2281  if (FAILED(hr))
2282  {
2283  WARN("Failed to initialize stateblock, hr %#x.\n", hr);
2287  heap_free(object);
2288  return hr;
2289  }
2290 
2291  TRACE("Created stateblock %p.\n", object);
2292  *stateblock = &object->IDirect3DStateBlock9_iface;
2293 
2294  return D3D_OK;
2295 }
2296 
2297 static HRESULT WINAPI d3d9_device_SetClipStatus(IDirect3DDevice9Ex *iface, const D3DCLIPSTATUS9 *clip_status)
2298 {
2300  HRESULT hr;
2301 
2302  TRACE("iface %p, clip_status %p.\n", iface, clip_status);
2303 
2305  hr = wined3d_device_set_clip_status(device->wined3d_device, (const struct wined3d_clip_status *)clip_status);
2307 
2308  return hr;
2309 }
2310 
2311 static HRESULT WINAPI d3d9_device_GetClipStatus(IDirect3DDevice9Ex *iface, D3DCLIPSTATUS9 *clip_status)
2312 {
2314  HRESULT hr;
2315 
2316  TRACE("iface %p, clip_status %p.\n", iface, clip_status);
2317 
2319  hr = wined3d_device_get_clip_status(device->wined3d_device, (struct wined3d_clip_status *)clip_status);
2321 
2322  return hr;
2323 }
2324 
2325 static HRESULT WINAPI d3d9_device_GetTexture(IDirect3DDevice9Ex *iface, DWORD stage, IDirect3DBaseTexture9 **texture)
2326 {
2329  struct d3d9_texture *texture_impl;
2330 
2331  TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
2332 
2333  if (!texture)
2334  return D3DERR_INVALIDCALL;
2335 
2337  if ((wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
2338  {
2340  *texture = &texture_impl->IDirect3DBaseTexture9_iface;
2342  }
2343  else
2344  {
2345  *texture = NULL;
2346  }
2348 
2349  return D3D_OK;
2350 }
2351 
2352 static HRESULT WINAPI d3d9_device_SetTexture(IDirect3DDevice9Ex *iface, DWORD stage, IDirect3DBaseTexture9 *texture)
2353 {
2355  struct d3d9_texture *texture_impl;
2356  HRESULT hr;
2357 
2358  TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
2359 
2361 
2363  hr = wined3d_device_set_texture(device->wined3d_device, stage,
2364  texture_impl ? texture_impl->wined3d_texture : NULL);
2365  if (SUCCEEDED(hr))
2366  {
2367  unsigned int i = stage >= D3DVERTEXTEXTURESAMPLER0 ? stage - D3DVERTEXTEXTURESAMPLER0 + 16 : stage;
2368 
2369  if (stage < ARRAY_SIZE(device->textures))
2370  device->textures[i] = texture_impl;
2371  }
2373 
2374  return hr;
2375 }
2376 
2378 {
2379  WINED3D_TSS_INVALID, /* 0, unused */
2380  WINED3D_TSS_COLOR_OP, /* 1, D3DTSS_COLOROP */
2381  WINED3D_TSS_COLOR_ARG1, /* 2, D3DTSS_COLORARG1 */
2382  WINED3D_TSS_COLOR_ARG2, /* 3, D3DTSS_COLORARG2 */
2383  WINED3D_TSS_ALPHA_OP, /* 4, D3DTSS_ALPHAOP */
2384  WINED3D_TSS_ALPHA_ARG1, /* 5, D3DTSS_ALPHAARG1 */
2385  WINED3D_TSS_ALPHA_ARG2, /* 6, D3DTSS_ALPHAARG2 */
2386  WINED3D_TSS_BUMPENV_MAT00, /* 7, D3DTSS_BUMPENVMAT00 */
2387  WINED3D_TSS_BUMPENV_MAT01, /* 8, D3DTSS_BUMPENVMAT01 */
2388  WINED3D_TSS_BUMPENV_MAT10, /* 9, D3DTSS_BUMPENVMAT10 */
2389  WINED3D_TSS_BUMPENV_MAT11, /* 10, D3DTSS_BUMPENVMAT11 */
2390  WINED3D_TSS_TEXCOORD_INDEX, /* 11, D3DTSS_TEXCOORDINDEX */
2391  WINED3D_TSS_INVALID, /* 12, unused */
2392  WINED3D_TSS_INVALID, /* 13, unused */
2393  WINED3D_TSS_INVALID, /* 14, unused */
2394  WINED3D_TSS_INVALID, /* 15, unused */
2395  WINED3D_TSS_INVALID, /* 16, unused */
2396  WINED3D_TSS_INVALID, /* 17, unused */
2397  WINED3D_TSS_INVALID, /* 18, unused */
2398  WINED3D_TSS_INVALID, /* 19, unused */
2399  WINED3D_TSS_INVALID, /* 20, unused */
2400  WINED3D_TSS_INVALID, /* 21, unused */
2401  WINED3D_TSS_BUMPENV_LSCALE, /* 22, D3DTSS_BUMPENVLSCALE */
2402  WINED3D_TSS_BUMPENV_LOFFSET, /* 23, D3DTSS_BUMPENVLOFFSET */
2403  WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
2404  WINED3D_TSS_INVALID, /* 25, unused */
2405  WINED3D_TSS_COLOR_ARG0, /* 26, D3DTSS_COLORARG0 */
2406  WINED3D_TSS_ALPHA_ARG0, /* 27, D3DTSS_ALPHAARG0 */
2407  WINED3D_TSS_RESULT_ARG, /* 28, D3DTSS_RESULTARG */
2408  WINED3D_TSS_INVALID, /* 29, unused */
2409  WINED3D_TSS_INVALID, /* 30, unused */
2410  WINED3D_TSS_INVALID, /* 31, unused */
2411  WINED3D_TSS_CONSTANT, /* 32, D3DTSS_CONSTANT */
2412 };
2413 
2414 static HRESULT WINAPI d3d9_device_GetTextureStageState(IDirect3DDevice9Ex *iface,
2416 {
2418 
2419  TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, stage, state, value);
2420 
2421  if (state >= ARRAY_SIZE(tss_lookup))
2422  {
2423  WARN("Invalid state %#x passed.\n", state);
2424  return D3D_OK;
2425  }
2426 
2430 
2431  return D3D_OK;
2432 }
2433 
2434 static HRESULT WINAPI d3d9_device_SetTextureStageState(IDirect3DDevice9Ex *iface,
2436 {
2438 
2439  TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, stage, state, value);
2440 
2441  if (state >= ARRAY_SIZE(tss_lookup))
2442  {
2443  WARN("Invalid state %#x passed.\n", state);
2444  return D3D_OK;
2445  }
2446 
2450 
2451  return D3D_OK;
2452 }
2453 
2454 static HRESULT WINAPI d3d9_device_GetSamplerState(IDirect3DDevice9Ex *iface,
2456 {
2458 
2459  TRACE("iface %p, sampler %u, state %#x, value %p.\n", iface, sampler, state, value);
2460 
2464 
2465  return D3D_OK;
2466 }
2467 
2470 {
2472 
2473  TRACE("iface %p, sampler %u, state %#x, value %#x.\n", iface, sampler, state, value);
2474 
2478 
2479  return D3D_OK;
2480 }
2481 
2482 static HRESULT WINAPI d3d9_device_ValidateDevice(IDirect3DDevice9Ex *iface, DWORD *pass_count)
2483 {
2485  HRESULT hr;
2486 
2487  TRACE("iface %p, pass_count %p.\n", iface, pass_count);
2488 
2490  hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
2492 
2493  return hr;
2494 }
2495 
2496 static HRESULT WINAPI d3d9_device_SetPaletteEntries(IDirect3DDevice9Ex *iface,
2497  UINT palette_idx, const PALETTEENTRY *entries)
2498 {
2499  WARN("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries);
2500 
2501  /* The d3d9 palette API is non-functional on Windows. Getters and setters are implemented,
2502  * and some drivers allow the creation of P8 surfaces. These surfaces can be copied to
2503  * other P8 surfaces with StretchRect, but cannot be converted to (A)RGB.
2504  *
2505  * Some older(dx7) cards may have support for P8 textures, but games cannot rely on this. */
2506  return D3D_OK;
2507 }
2508 
2509 static HRESULT WINAPI d3d9_device_GetPaletteEntries(IDirect3DDevice9Ex *iface,
2510  UINT palette_idx, PALETTEENTRY *entries)
2511 {
2512  FIXME("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries);
2513 
2514  return D3DERR_INVALIDCALL;
2515 }
2516 
2517 static HRESULT WINAPI d3d9_device_SetCurrentTexturePalette(IDirect3DDevice9Ex *iface, UINT palette_idx)
2518 {
2519  WARN("iface %p, palette_idx %u unimplemented.\n", iface, palette_idx);
2520 
2521  return D3D_OK;
2522 }
2523 
2524 static HRESULT WINAPI d3d9_device_GetCurrentTexturePalette(IDirect3DDevice9Ex *iface, UINT *palette_idx)
2525 {
2526  FIXME("iface %p, palette_idx %p.\n", iface, palette_idx);
2527 
2528  return D3DERR_INVALIDCALL;
2529 }
2530 
2531 static HRESULT WINAPI d3d9_device_SetScissorRect(IDirect3DDevice9Ex *iface, const RECT *rect)
2532 {
2534 
2535  TRACE("iface %p, rect %p.\n", iface, rect);
2536 
2538  wined3d_device_set_scissor_rect(device->wined3d_device, rect);
2540 
2541  return D3D_OK;
2542 }
2543 
2544 static HRESULT WINAPI d3d9_device_GetScissorRect(IDirect3DDevice9Ex *iface, RECT *rect)
2545 {
2547 
2548  TRACE("iface %p, rect %p.\n", iface, rect);
2549 
2551  wined3d_device_get_scissor_rect(device->wined3d_device, rect);
2553 
2554  return D3D_OK;
2555 }
2556 
2557 static HRESULT WINAPI d3d9_device_SetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface, BOOL software)
2558 {
2560 
2561  TRACE("iface %p, software %#x.\n", iface, software);
2562 
2564  wined3d_device_set_software_vertex_processing(device->wined3d_device, software);
2566 
2567  return D3D_OK;
2568 }
2569 
2570 static BOOL WINAPI d3d9_device_GetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface)
2571 {
2573  BOOL ret;
2574 
2575  TRACE("iface %p.\n", iface);
2576 
2580 
2581  return ret;
2582 }
2583 
2584 static HRESULT WINAPI d3d9_device_SetNPatchMode(IDirect3DDevice9Ex *iface, float segment_count)
2585 {
2587  HRESULT hr;
2588 
2589  TRACE("iface %p, segment_count %.8e.\n", iface, segment_count);
2590 
2592  hr = wined3d_device_set_npatch_mode(device->wined3d_device, segment_count);
2594 
2595  return hr;
2596 }
2597 
2598 static float WINAPI d3d9_device_GetNPatchMode(IDirect3DDevice9Ex *iface)
2599 {
2601  float ret;
2602 
2603  TRACE("iface %p.\n", iface);
2604 
2606  ret = wined3d_device_get_npatch_mode(device->wined3d_device);
2608 
2609  return ret;
2610 }
2611 
2612 /* wined3d critical section must be taken by the caller. */
2614 {
2615  unsigned int i;
2616 
2617  for (i = 0; i < ARRAY_SIZE(device->textures); ++i)
2618  if (device->textures[i])
2620 }
2621 
2622 static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface,
2623  D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count)
2624 {
2626  HRESULT hr;
2627 
2628  TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n",
2629  iface, primitive_type, start_vertex, primitive_count);
2630 
2632  if (!device->has_vertex_declaration)
2633  {
2635  WARN("Called without a valid vertex declaration set.\n");
2636  return D3DERR_INVALIDCALL;
2637  }
2639  wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
2640  hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex,
2641  vertex_count_from_primitive_count(primitive_type, primitive_count));
2642  if (SUCCEEDED(hr))
2645 
2646  return hr;
2647 }
2648 
2649 static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface,
2650  D3DPRIMITIVETYPE primitive_type, INT base_vertex_idx, UINT min_vertex_idx,
2651  UINT vertex_count, UINT start_idx, UINT primitive_count)
2652 {
2654  HRESULT hr;
2655 
2656  TRACE("iface %p, primitive_type %#x, base_vertex_idx %u, min_vertex_idx %u, "
2657  "vertex_count %u, start_idx %u, primitive_count %u.\n",
2658  iface, primitive_type, base_vertex_idx, min_vertex_idx,
2659  vertex_count, start_idx, primitive_count);
2660 
2662  if (!device->has_vertex_declaration)
2663  {
2665  WARN("Called without a valid vertex declaration set.\n");
2666  return D3DERR_INVALIDCALL;
2667  }
2669  wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx);
2670  wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
2671  hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, start_idx,
2672  vertex_count_from_primitive_count(primitive_type, primitive_count));
2673  if (SUCCEEDED(hr))
2676 
2677  return hr;
2678 }
2679 
2680 /* The caller is responsible for wined3d locking */
2682 {
2683  HRESULT hr;
2684 
2685  if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
2686  {
2687  UINT size = max(device->vertex_buffer_size * 2, min_size);
2688  struct wined3d_buffer_desc desc;
2689  struct wined3d_buffer *buffer;
2690 
2691  TRACE("Growing vertex buffer to %u bytes.\n", size);
2692 
2693  desc.byte_width = size;
2695  desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
2697  desc.misc_flags = 0;
2698  desc.structure_byte_stride = 0;
2699 
2700  if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
2702  {
2703  ERR("Failed to create vertex buffer, hr %#x.\n", hr);
2704  return hr;
2705  }
2706 
2707  if (device->vertex_buffer)
2708  wined3d_buffer_decref(device->vertex_buffer);
2709 
2710  device->vertex_buffer = buffer;
2711  device->vertex_buffer_size = size;
2712  device->vertex_buffer_pos = 0;
2713  }
2714  return D3D_OK;
2715 }
2716 
2717 static HRESULT WINAPI d3d9_device_DrawPrimitiveUP(IDirect3DDevice9Ex *iface,
2718  D3DPRIMITIVETYPE primitive_type, UINT primitive_count, const void *data, UINT stride)
2719 {
2721  HRESULT hr;
2722  UINT vtx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
2724  struct wined3d_box wined3d_box = {0};
2725  UINT size = vtx_count * stride;
2726  struct wined3d_resource *vb;
2727  UINT vb_pos, align;
2728 
2729  TRACE("iface %p, primitive_type %#x, primitive_count %u, data %p, stride %u.\n",
2730  iface, primitive_type, primitive_count, data, stride);
2731 
2732  if (!primitive_count)
2733  {
2734  WARN("primitive_count is 0, returning D3D_OK\n");
2735  return D3D_OK;
2736  }
2737 
2739 
2740  if (!device->has_vertex_declaration)
2741  {
2743  WARN("Called without a valid vertex declaration set.\n");
2744  return D3DERR_INVALIDCALL;
2745  }
2746 
2748  if (FAILED(hr))
2749  goto done;
2750 
2751  vb_pos = device->vertex_buffer_pos;
2752  align = vb_pos % stride;
2753  if (align) align = stride - align;
2754  if (vb_pos + size + align > device->vertex_buffer_size)
2755  vb_pos = 0;
2756  else
2757  vb_pos += align;
2758 
2759  wined3d_box.left = vb_pos;
2760  wined3d_box.right = vb_pos + size;
2761  vb = wined3d_buffer_get_resource(device->vertex_buffer);
2764  goto done;
2766  wined3d_resource_unmap(vb, 0);
2767  device->vertex_buffer_pos = vb_pos + size;
2768 
2769  hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
2770  if (FAILED(hr))
2771  goto done;
2772 
2774  wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
2775  hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vtx_count);
2776  wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
2777  if (SUCCEEDED(hr))
2779 
2780 done:
2782  return hr;
2783 }
2784 
2785 /* The caller is responsible for wined3d locking */
2787 {
2788  HRESULT hr;
2789 
2790  if (device->index_buffer_size < min_size || !device->index_buffer)
2791  {
2792  UINT size = max(device->index_buffer_size * 2, min_size);
2793  struct wined3d_buffer_desc desc;
2794  struct wined3d_buffer *buffer;
2795 
2796  TRACE("Growing index buffer to %u bytes.\n", size);
2797 
2798  desc.byte_width = size;
2800  desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
2802  desc.misc_flags = 0;
2803  desc.structure_byte_stride = 0;
2804 
2805  if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
2807  {
2808  ERR("Failed to create index buffer, hr %#x.\n", hr);
2809  return hr;
2810  }
2811 
2812  if (device->index_buffer)
2813  wined3d_buffer_decref(device->index_buffer);
2814 
2815  device->index_buffer = buffer;
2816  device->index_buffer_size = size;
2817  device->index_buffer_pos = 0;
2818  }
2819  return D3D_OK;
2820 }
2821 
2822 static HRESULT WINAPI d3d9_device_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *iface,
2823  D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count,
2824  UINT primitive_count, const void *index_data, D3DFORMAT index_format,
2825  const void *vertex_data, UINT vertex_stride)
2826 {
2827  UINT idx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
2829  UINT idx_fmt_size = index_format == D3DFMT_INDEX16 ? 2 : 4;
2830  UINT vtx_size = vertex_count * vertex_stride;
2831  UINT idx_size = idx_count * idx_fmt_size;
2833  struct wined3d_box wined3d_box = {0};
2834  struct wined3d_resource *ib, *vb;
2835  UINT vb_pos, ib_pos, align;
2836  HRESULT hr;
2837 
2838  TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, primitive_count %u, "
2839  "index_data %p, index_format %#x, vertex_data %p, vertex_stride %u.\n",
2840  iface, primitive_type, min_vertex_idx, vertex_count, primitive_count,
2841  index_data, index_format, vertex_data, vertex_stride);
2842 
2843  if (!primitive_count)
2844  {
2845  WARN("primitive_count is 0, returning D3D_OK.\n");
2846  return D3D_OK;
2847  }
2848 
2850 
2851  if (!device->has_vertex_declaration)
2852  {
2854  WARN("Called without a valid vertex declaration set.\n");
2855  return D3DERR_INVALIDCALL;
2856  }
2857 
2859  if (FAILED(hr))
2860  goto done;
2861 
2862  vb_pos = device->vertex_buffer_pos;
2863  align = vb_pos % vertex_stride;
2864  if (align) align = vertex_stride - align;
2865  if (vb_pos + vtx_size + align > device->vertex_buffer_size)
2866  vb_pos = 0;
2867  else
2868  vb_pos += align;
2869 
2870  wined3d_box.left = vb_pos;
2871  wined3d_box.right = vb_pos + vtx_size;
2872  vb = wined3d_buffer_get_resource(device->vertex_buffer);
2875  goto done;
2876  memcpy(wined3d_map_desc.data, (char *)vertex_data + min_vertex_idx * vertex_stride, vtx_size);
2877  wined3d_resource_unmap(vb, 0);
2878  device->vertex_buffer_pos = vb_pos + vtx_size;
2879 
2881  if (FAILED(hr))
2882  goto done;
2883 
2884  ib_pos = device->index_buffer_pos;
2885  align = ib_pos % idx_fmt_size;
2886  if (align) align = idx_fmt_size - align;
2887  if (ib_pos + idx_size + align > device->index_buffer_size)
2888  ib_pos = 0;
2889  else
2890  ib_pos += align;
2891 
2892  wined3d_box.left = ib_pos;
2893  wined3d_box.right = ib_pos + idx_size;
2894  ib = wined3d_buffer_get_resource(device->index_buffer);
2897  goto done;
2898  memcpy(wined3d_map_desc.data, index_data, idx_size);
2899  wined3d_resource_unmap(ib, 0);
2900  device->index_buffer_pos = ib_pos + idx_size;
2901 
2902  hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vertex_stride);
2903  if (FAILED(hr))
2904  goto done;
2905 
2907  wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer,
2908  wined3dformat_from_d3dformat(index_format), 0);
2909  wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vertex_stride - min_vertex_idx);
2910 
2911  wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
2912  hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / idx_fmt_size, idx_count);
2913 
2914  wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
2916  wined3d_device_set_base_vertex_index(device->wined3d_device, 0);
2917 
2918  if (SUCCEEDED(hr))
2920 
2921 done:
2923  return hr;
2924 }
2925 
2926 static HRESULT WINAPI d3d9_device_ProcessVertices(IDirect3DDevice9Ex *iface,
2927  UINT src_start_idx, UINT dst_idx, UINT vertex_count, IDirect3DVertexBuffer9 *dst_buffer,
2928  IDirect3DVertexDeclaration9 *declaration, DWORD flags)
2929 {
2931  struct d3d9_vertexbuffer *dst_impl = unsafe_impl_from_IDirect3DVertexBuffer9(dst_buffer);
2933  HRESULT hr;
2934 
2935  TRACE("iface %p, src_start_idx %u, dst_idx %u, vertex_count %u, dst_buffer %p, declaration %p, flags %#x.\n",
2936  iface, src_start_idx, dst_idx, vertex_count, dst_buffer, declaration, flags);
2937 
2939  hr = wined3d_device_process_vertices(device->wined3d_device, src_start_idx, dst_idx, vertex_count,
2940  dst_impl->wined3d_buffer, decl_impl ? decl_impl->wined3d_declaration : NULL,
2941  flags, dst_impl->fvf);
2943 
2944  return hr;
2945 }
2946 
2947 static HRESULT WINAPI d3d9_device_CreateVertexDeclaration(IDirect3DDevice9Ex *iface,
2948  const D3DVERTEXELEMENT9 *elements, IDirect3DVertexDeclaration9 **declaration)
2949 {
2952  HRESULT hr;
2953 
2954  TRACE("iface %p, elements %p, declaration %p.\n", iface, elements, declaration);
2955 
2956  if (!declaration)
2957  {
2958  WARN("Caller passed a NULL declaration, returning D3DERR_INVALIDCALL.\n");
2959  return D3DERR_INVALIDCALL;
2960  }
2961 
2963  *declaration = &object->IDirect3DVertexDeclaration9_iface;
2964 
2965  return hr;
2966 }
2967 
2968 static HRESULT WINAPI d3d9_device_SetVertexDeclaration(IDirect3DDevice9Ex *iface,
2969  IDirect3DVertexDeclaration9 *declaration)
2970 {
2973 
2974  TRACE("iface %p, declaration %p.\n", iface, declaration);
2975 
2978  decl_impl ? decl_impl->wined3d_declaration : NULL);
2979  device->has_vertex_declaration = !!decl_impl;
2981 
2982  return D3D_OK;
2983 }
2984 
2985 static HRESULT WINAPI d3d9_device_GetVertexDeclaration(IDirect3DDevice9Ex *iface,
2986  IDirect3DVertexDeclaration9 **declaration)
2987 {
2989  struct wined3d_vertex_declaration *wined3d_declaration;
2990  struct d3d9_vertex_declaration *declaration_impl;
2991 
2992  TRACE("iface %p, declaration %p.\n", iface, declaration);
2993 
2994  if (!declaration) return D3DERR_INVALIDCALL;
2995 
2998  {
3000  *declaration = &declaration_impl->IDirect3DVertexDeclaration9_iface;
3002  }
3003  else
3004  {
3005  *declaration = NULL;
3006  }
3008 
3009  TRACE("Returning %p.\n", *declaration);
3010  return D3D_OK;
3011 }
3012 
3014 {
3015  struct wined3d_vertex_declaration *wined3d_declaration;
3016  struct fvf_declaration *fvf_decls = device->fvf_decls;
3017  struct d3d9_vertex_declaration *d3d9_declaration;
3019  int p, low, high; /* deliberately signed */
3020  HRESULT hr;
3021 
3022  TRACE("Searching for declaration for fvf %08x... ", fvf);
3023 
3024  low = 0;
3025  high = device->fvf_decl_count - 1;
3026  while (low <= high)
3027  {
3028  p = (low + high) >> 1;
3029  TRACE("%d ", p);
3030 
3031  if (fvf_decls[p].fvf == fvf)
3032  {
3033  TRACE("found %p.\n", fvf_decls[p].decl);
3034  return fvf_decls[p].decl;
3035  }
3036 
3037  if (fvf_decls[p].fvf < fvf)
3038  low = p + 1;
3039  else
3040  high = p - 1;
3041  }
3042  TRACE("not found. Creating and inserting at position %d.\n", low);
3043 
3045  return NULL;
3046 
3047  hr = d3d9_vertex_declaration_create(device, elements, &d3d9_declaration);
3049  if (FAILED(hr))
3050  return NULL;
3051 
3052  if (device->fvf_decl_size == device->fvf_decl_count)
3053  {
3054  UINT grow = max(device->fvf_decl_size / 2, 8);
3055 
3056  if (!(fvf_decls = heap_realloc(fvf_decls, sizeof(*fvf_decls) * (device->fvf_decl_size + grow))))
3057  {
3059  return NULL;
3060  }
3061  device->fvf_decls = fvf_decls;
3062  device->fvf_decl_size += grow;
3063  }
3064 
3065  d3d9_declaration->fvf = fvf;
3066  wined3d_declaration = d3d9_declaration->wined3d_declaration;
3069 
3070  memmove(fvf_decls + low + 1, fvf_decls + low, sizeof(*fvf_decls) * (device->fvf_decl_count - low));
3071  fvf_decls[low].decl = wined3d_declaration;
3072  fvf_decls[low].fvf = fvf;
3073  ++device->fvf_decl_count;
3074 
3075  TRACE("Returning %p. %u declarations in array.\n", wined3d_declaration, device->fvf_decl_count);
3076 
3077  return wined3d_declaration;
3078 }
3079 
3080 static HRESULT WINAPI d3d9_device_SetFVF(IDirect3DDevice9Ex *iface, DWORD fvf)
3081 {
3083  struct wined3d_vertex_declaration *decl;
3084 
3085  TRACE("iface %p, fvf %#x.\n", iface, fvf);
3086 
3087  if (!fvf)
3088  {
3089  WARN("%#x is not a valid FVF.\n", fvf);
3090  return D3D_OK;
3091  }
3092 
3094  if (!(decl = device_get_fvf_declaration(device, fvf)))
3095  {
3097  ERR("Failed to create a vertex declaration for fvf %#x.\n", fvf);
3099  }
3100 
3101  wined3d_device_set_vertex_declaration(device->wined3d_device, decl);
3102  device->has_vertex_declaration = TRUE;
3104 
3105  return D3D_OK;
3106 }
3107 
3108 static HRESULT WINAPI d3d9_device_GetFVF(IDirect3DDevice9Ex *iface, DWORD *fvf)
3109 {
3111  struct wined3d_vertex_declaration *wined3d_declaration;
3112  struct d3d9_vertex_declaration *d3d9_declaration;
3113 
3114  TRACE("iface %p, fvf %p.\n", iface, fvf);
3115 
3118  {
3120  *fvf = d3d9_declaration->fvf;
3121  }
3122  else
3123  {
3124  *fvf = 0;
3125  }
3127 
3128  TRACE("Returning FVF %#x.\n", *fvf);
3129 
3130  return D3D_OK;
3131 }
3132 
3133 static HRESULT WINAPI d3d9_device_CreateVertexShader(IDirect3DDevice9Ex *iface,
3134  const DWORD *byte_code, IDirect3DVertexShader9 **shader)
3135 {
3137  struct d3d9_vertexshader *object;
3138  HRESULT hr;
3139 
3140  TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
3141 
3142  if (!(object = heap_alloc_zero(sizeof(*object))))
3143  return E_OUTOFMEMORY;
3144 
3145  hr = vertexshader_init(object, device, byte_code);
3146  if (FAILED(hr))
3147  {
3148  WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
3149  heap_free(object);
3150  return hr;
3151  }
3152 
3153  TRACE("Created vertex shader %p.\n", object);
3154  *shader = &object->IDirect3DVertexShader9_iface;
3155 
3156  return D3D_OK;
3157 }
3158 
3159 static HRESULT WINAPI d3d9_device_SetVertexShader(IDirect3DDevice9Ex *iface, IDirect3DVertexShader9 *shader)
3160 {
3163 
3164  TRACE("iface %p, shader %p.\n", iface, shader);
3165 
3167  wined3d_device_set_vertex_shader(device->wined3d_device,
3168  shader_obj ? shader_obj->wined3d_shader : NULL);
3170 
3171  return D3D_OK;
3172 }
3173 
3174 static HRESULT WINAPI d3d9_device_GetVertexShader(IDirect3DDevice9Ex *iface, IDirect3DVertexShader9 **shader)
3175 {
3177  struct d3d9_vertexshader *shader_impl;
3179 
3180  TRACE("iface %p, shader %p.\n", iface, shader);
3181 
3183  if ((wined3d_shader = wined3d_device_get_vertex_shader(device->wined3d_device)))
3184  {
3186  *shader = &shader_impl->IDirect3DVertexShader9_iface;
3188  }
3189  else
3190  {
3191  *shader = NULL;
3192  }
3194 
3195  TRACE("Returning %p.\n", *shader);
3196 
3197  return D3D_OK;
3198 }
3199 
3200 static HRESULT WINAPI d3d9_device_SetVertexShaderConstantF(IDirect3DDevice9Ex *iface,
3201  UINT reg_idx, const float *data, UINT count)
3202 {
3204  HRESULT hr;
3205 
3206  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3207 
3208  if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF)
3209  {
3210  WARN("Trying to access %u constants, but d3d9 only supports %u\n",
3212  return D3DERR_INVALIDCALL;
3213  }
3214 
3216  hr = wined3d_device_set_vs_consts_f(device->wined3d_device,
3217  reg_idx, count, (const struct wined3d_vec4 *)data);
3219 
3220  return hr;
3221 }
3222 
3223 static HRESULT WINAPI d3d9_device_GetVertexShaderConstantF(IDirect3DDevice9Ex *iface,
3224  UINT reg_idx, float *data, UINT count)
3225 {
3227  HRESULT hr;
3228 
3229  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3230 
3231  if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF)
3232  {
3233  WARN("Trying to access %u constants, but d3d9 only supports %u\n",
3235  return D3DERR_INVALIDCALL;
3236  }
3237 
3239  hr = wined3d_device_get_vs_consts_f(device->wined3d_device,
3240  reg_idx, count, (struct wined3d_vec4 *)data);
3242 
3243  return hr;
3244 }
3245 
3246 static HRESULT WINAPI d3d9_device_SetVertexShaderConstantI(IDirect3DDevice9Ex *iface,
3247  UINT reg_idx, const int *data, UINT count)
3248 {
3250  HRESULT hr;
3251 
3252  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3253 
3255  hr = wined3d_device_set_vs_consts_i(device->wined3d_device,
3256  reg_idx, count, (const struct wined3d_ivec4 *)data);
3258 
3259  return hr;
3260 }
3261 
3262 static HRESULT WINAPI d3d9_device_GetVertexShaderConstantI(IDirect3DDevice9Ex *iface,
3263  UINT reg_idx, int *data, UINT count)
3264 {
3266  HRESULT hr;
3267 
3268  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3269 
3271  hr = wined3d_device_get_vs_consts_i(device->wined3d_device,
3272  reg_idx, count, (struct wined3d_ivec4 *)data);
3274 
3275  return hr;
3276 }
3277 
3278 static HRESULT WINAPI d3d9_device_SetVertexShaderConstantB(IDirect3DDevice9Ex *iface,
3279  UINT reg_idx, const BOOL *data, UINT count)
3280 {
3282  HRESULT hr;
3283 
3284  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3285 
3287  hr = wined3d_device_set_vs_consts_b(device->wined3d_device, reg_idx, count, data);
3289 
3290  return hr;
3291 }
3292 
3293 static HRESULT WINAPI d3d9_device_GetVertexShaderConstantB(IDirect3DDevice9Ex *iface,
3294  UINT reg_idx, BOOL *data, UINT count)
3295 {
3297  HRESULT hr;
3298 
3299  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3300 
3302  hr = wined3d_device_get_vs_consts_b(device->wined3d_device, reg_idx, count, data);
3304 
3305  return hr;
3306 }
3307 
3308 static HRESULT WINAPI d3d9_device_SetStreamSource(IDirect3DDevice9Ex *iface,
3309  UINT stream_idx, IDirect3DVertexBuffer9 *buffer, UINT offset, UINT stride)
3310 {
3313  HRESULT hr;
3314 
3315  TRACE("iface %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
3316  iface, stream_idx, buffer, offset, stride);
3317 
3319  hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx,
3320  buffer_impl ? buffer_impl->wined3d_buffer : NULL, offset, stride);
3322 
3323  return hr;
3324 }
3325 
3326 static HRESULT WINAPI d3d9_device_GetStreamSource(IDirect3DDevice9Ex *iface,
3327  UINT stream_idx, IDirect3DVertexBuffer9 **buffer, UINT *offset, UINT *stride)
3328 {
3330  struct d3d9_vertexbuffer *buffer_impl;
3332  HRESULT hr;
3333 
3334  TRACE("iface %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
3335  iface, stream_idx, buffer, offset, stride);
3336 
3337  if (!buffer)
3338  return D3DERR_INVALIDCALL;
3339 
3341  hr = wined3d_device_get_stream_source(device->wined3d_device, stream_idx, &wined3d_buffer, offset, stride);
3342  if (SUCCEEDED(hr) && wined3d_buffer)
3343  {
3345  *buffer = &buffer_impl->IDirect3DVertexBuffer9_iface;
3347  }
3348  else
3349  {
3350  if (FAILED(hr))
3351  FIXME("Call to GetStreamSource failed %p %p\n", offset, stride);
3352  *buffer = NULL;
3353  }
3355 
3356  return hr;
3357 }
3358 
3359 static HRESULT WINAPI d3d9_device_SetStreamSourceFreq(IDirect3DDevice9Ex *iface, UINT stream_idx, UINT freq)
3360 {
3362  HRESULT hr;
3363 
3364  TRACE("iface %p, stream_idx %u, freq %u.\n", iface, stream_idx, freq);
3365 
3367  hr = wined3d_device_set_stream_source_freq(device->wined3d_device, stream_idx, freq);
3369 
3370  return hr;
3371 }
3372 
3373 static HRESULT WINAPI d3d9_device_GetStreamSourceFreq(IDirect3DDevice9Ex *iface, UINT stream_idx, UINT *freq)
3374 {
3376  HRESULT hr;
3377 
3378  TRACE("iface %p, stream_idx %u, freq %p.\n", iface, stream_idx, freq);
3379 
3381  hr = wined3d_device_get_stream_source_freq(device->wined3d_device, stream_idx, freq);
3383 
3384  return hr;
3385 }
3386 
3387 static HRESULT WINAPI d3d9_device_SetIndices(IDirect3DDevice9Ex *iface, IDirect3DIndexBuffer9 *buffer)
3388 {
3391 
3392  TRACE("iface %p, buffer %p.\n", iface, buffer);
3393 
3395  wined3d_device_set_index_buffer(device->wined3d_device,
3396  ib ? ib->wined3d_buffer : NULL, ib ? ib->format : WINED3DFMT_UNKNOWN, 0);
3398 
3399  return D3D_OK;
3400 }
3401 
3402 static HRESULT WINAPI d3d9_device_GetIndices(IDirect3DDevice9Ex *iface, IDirect3DIndexBuffer9 **buffer)
3403 {
3407  struct d3d9_indexbuffer *buffer_impl;
3408 
3409  TRACE("iface %p, buffer %p.\n", iface, buffer);
3410 
3411  if (!buffer)
3412  return D3DERR_INVALIDCALL;
3413 
3416  {
3418  *buffer = &buffer_impl->IDirect3DIndexBuffer9_iface;
3420  }
3421  else
3422  {
3423  *buffer = NULL;
3424  }
3426 
3427  return D3D_OK;
3428 }
3429 
3430 static HRESULT WINAPI d3d9_device_CreatePixelShader(IDirect3DDevice9Ex *iface,
3431  const DWORD *byte_code, IDirect3DPixelShader9 **shader)
3432 {
3434  struct d3d9_pixelshader *object;
3435  HRESULT hr;
3436 
3437  TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
3438 
3439  if (!(object = heap_alloc_zero(sizeof(*object))))
3440  {
3441  FIXME("Failed to allocate pixel shader memory.\n");
3442  return E_OUTOFMEMORY;
3443  }
3444 
3445  hr = pixelshader_init(object, device, byte_code);
3446  if (FAILED(hr))
3447  {
3448  WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
3449  heap_free(object);
3450  return hr;
3451  }
3452 
3453  TRACE("Created pixel shader %p.\n", object);
3454  *shader = &object->IDirect3DPixelShader9_iface;
3455 
3456  return D3D_OK;
3457 }
3458 
3459 static HRESULT WINAPI d3d9_device_SetPixelShader(IDirect3DDevice9Ex *iface, IDirect3DPixelShader9 *shader)
3460 {
3463 
3464  TRACE("iface %p, shader %p.\n", iface, shader);
3465 
3467  wined3d_device_set_pixel_shader(device->wined3d_device,
3468  shader_obj ? shader_obj->wined3d_shader : NULL);
3470 
3471  return D3D_OK;
3472 }
3473 
3474 static HRESULT WINAPI d3d9_device_GetPixelShader(IDirect3DDevice9Ex *iface, IDirect3DPixelShader9 **shader)
3475 {
3477  struct d3d9_pixelshader *shader_impl;
3479 
3480  TRACE("iface %p, shader %p.\n", iface, shader);
3481 
3482  if (!shader) return D3DERR_INVALIDCALL;
3483 
3485  if ((wined3d_shader = wined3d_device_get_pixel_shader(device->wined3d_device)))
3486  {
3488  *shader = &shader_impl->IDirect3DPixelShader9_iface;
3490  }
3491  else
3492  {
3493  *shader = NULL;
3494  }
3496 
3497  TRACE("Returning %p.\n", *shader);
3498 
3499  return D3D_OK;
3500 }
3501 
3502 static HRESULT WINAPI d3d9_device_SetPixelShaderConstantF(IDirect3DDevice9Ex *iface,
3503  UINT reg_idx, const float *data, UINT count)
3504 {
3506  HRESULT hr;
3507 
3508  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3509 
3511  hr = wined3d_device_set_ps_consts_f(device->wined3d_device,
3512  reg_idx, count, (const struct wined3d_vec4 *)data);
3514 
3515  return hr;
3516 }
3517 
3518 static HRESULT WINAPI d3d9_device_GetPixelShaderConstantF(IDirect3DDevice9Ex *iface,
3519  UINT reg_idx, float *data, UINT count)
3520 {
3522  HRESULT hr;
3523 
3524  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3525 
3527  hr = wined3d_device_get_ps_consts_f(device->wined3d_device,
3528  reg_idx, count, (struct wined3d_vec4 *)data);
3530 
3531  return hr;
3532 }
3533 
3534 static HRESULT WINAPI d3d9_device_SetPixelShaderConstantI(IDirect3DDevice9Ex *iface,
3535  UINT reg_idx, const int *data, UINT count)
3536 {
3538  HRESULT hr;
3539 
3540  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3541 
3543  hr = wined3d_device_set_ps_consts_i(device->wined3d_device,
3544  reg_idx, count, (const struct wined3d_ivec4 *)data);
3546 
3547  return hr;
3548 }
3549 
3550 static HRESULT WINAPI d3d9_device_GetPixelShaderConstantI(IDirect3DDevice9Ex *iface,
3551  UINT reg_idx, int *data, UINT count)
3552 {
3554  HRESULT hr;
3555 
3556  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3557 
3559  hr = wined3d_device_get_ps_consts_i(device->wined3d_device,
3560  reg_idx, count, (struct wined3d_ivec4 *)data);
3562 
3563  return hr;
3564 }
3565 
3566 static HRESULT WINAPI d3d9_device_SetPixelShaderConstantB(IDirect3DDevice9Ex *iface,
3567  UINT reg_idx, const BOOL *data, UINT count)
3568 {
3570  HRESULT hr;
3571 
3572  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3573 
3575  hr = wined3d_device_set_ps_consts_b(device->wined3d_device, reg_idx, count, data);
3577 
3578  return hr;
3579 }
3580 
3581 static HRESULT WINAPI d3d9_device_GetPixelShaderConstantB(IDirect3DDevice9Ex *iface,
3582  UINT reg_idx, BOOL *data, UINT count)
3583 {
3585  HRESULT hr;
3586 
3587  TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3588 
3590  hr = wined3d_device_get_ps_consts_b(device->wined3d_device, reg_idx, count, data);
3592 
3593  return hr;
3594 }
3595 
3596 static HRESULT WINAPI d3d9_device_DrawRectPatch(IDirect3DDevice9Ex *iface, UINT handle,
3597  const float *segment_count, const D3DRECTPATCH_INFO *patch_info)
3598 {
3599  FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
3600  iface, handle, segment_count, patch_info);
3601  return D3D_OK;
3602 }
3603 
3604 static HRESULT WINAPI d3d9_device_DrawTriPatch(IDirect3DDevice9Ex *iface, UINT handle,
3605  const float *segment_count, const D3DTRIPATCH_INFO *patch_info)
3606 {
3607  FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
3608  iface, handle, segment_count, patch_info);
3609  return D3D_OK;
3610 }
3611 
3612 static HRESULT WINAPI d3d9_device_DeletePatch(IDirect3DDevice9Ex *iface, UINT handle)
3613 {
3614  FIXME("iface %p, handle %#x unimplemented.\n", iface, handle);
3615  return D3DERR_INVALIDCALL;
3616 }
3617 
3618 static HRESULT WINAPI d3d9_device_CreateQuery(IDirect3DDevice9Ex *iface, D3DQUERYTYPE type, IDirect3DQuery9 **query)
3619 {
3621  struct d3d9_query *object;
3622  HRESULT hr;
3623 
3624  TRACE("iface %p, type %#x, query %p.\n", iface, type, query);
3625 
3626  if (!(object = heap_alloc_zero(sizeof(*object))))
3627  return E_OUTOFMEMORY;
3628 
3629  hr = query_init(object, device, type);
3630  if (FAILED(hr))
3631  {
3632  WARN("Failed to initialize query, hr %#x.\n", hr);
3633  heap_free(object);
3634  return hr;
3635  }
3636 
3637  TRACE("Created query %p.\n", object);
3638  if (query) *query = &object->IDirect3DQuery9_iface;
3639  else IDirect3DQuery9_Release(&object->IDirect3DQuery9_iface);
3640 
3641  return D3D_OK;
3642 }
3643 
3644 static HRESULT WINAPI d3d9_device_SetConvolutionMonoKernel(IDirect3DDevice9Ex *iface,
3645  UINT width, UINT height, float *rows, float *columns)
3646 {
3647  FIXME("iface %p, width %u, height %u, rows %p, columns %p stub!\n",
3648  iface, width, height, rows, columns);
3649 
3650  return E_NOTIMPL;
3651 }
3652 
3653 static HRESULT WINAPI d3d9_device_ComposeRects(IDirect3DDevice9Ex *iface,
3654  IDirect3DSurface9 *src_surface, IDirect3DSurface9 *dst_surface, IDirect3DVertexBuffer9 *src_descs,
3655  UINT rect_count, IDirect3DVertexBuffer9 *dst_descs, D3DCOMPOSERECTSOP operation, INT offset_x, INT offset_y)
3656 {
3657  FIXME("iface %p, src_surface %p, dst_surface %p, src_descs %p, rect_count %u, "
3658  "dst_descs %p, operation %#x, offset_x %u, offset_y %u stub!\n",
3659  iface, src_surface, dst_surface, src_descs, rect_count,
3660  dst_descs, operation, offset_x, offset_y);
3661 
3662  return E_NOTIMPL;
3663 }
3664 
3665 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex *iface,
3666  const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
3667  const RGNDATA *dirty_region, DWORD flags)
3668 {
3670  UINT i;
3671  HRESULT hr;
3672 
3673  TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n",
3674  iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect),
3675  dst_window_override, dirty_region, flags);
3676 
3677  if (device->device_state != D3D9_DEVICE_STATE_OK)
3678  return S_PRESENT_OCCLUDED;
3679 
3680  if (dirty_region)
3681  FIXME("Ignoring dirty_region %p.\n", dirty_region);
3682 
3684  for (i = 0; i < device->implicit_swapchain_count; ++i)
3685  {
3686  if (FAILED(hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain,
3687  src_rect, dst_rect, dst_window_override, 0, flags)))
3688  {
3690  return hr;
3691  }
3692  }
3694 
3695  return D3D_OK;
3696 }
3697 
3698 static HRESULT WINAPI d3d9_device_GetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT *priority)
3699 {
3700  FIXME("iface %p, priority %p stub!\n", iface, priority);
3701 
3702  return E_NOTIMPL;
3703 }
3704 
3705 static HRESULT WINAPI d3d9_device_SetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT priority)
3706 {
3707  FIXME("iface %p, priority %d stub!\n", iface, priority);
3708 
3709  return E_NOTIMPL;
3710 }
3711 
3712 static HRESULT WINAPI d3d9_device_WaitForVBlank(IDirect3DDevice9Ex *iface, UINT swapchain_idx)
3713 {
3714  FIXME("iface %p, swapchain_idx %u stub!\n", iface, swapchain_idx);
3715 
3716  return E_NOTIMPL;
3717 }
3718 
3719 static HRESULT WINAPI d3d9_device_CheckResourceResidency(IDirect3DDevice9Ex *iface,
3720  IDirect3DResource9 **resources, UINT32 resource_count)
3721 {
3722  FIXME("iface %p, resources %p, resource_count %u stub!\n",
3723  iface, resources, resource_count);
3724 
3725  return E_NOTIMPL;
3726 }
3727 
3728 static HRESULT WINAPI d3d9_device_SetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT max_latency)
3729 {
3730  TRACE("iface %p, max_latency %u.\n", iface, max_latency);
3731 
3732  if (max_latency)
3733  FIXME("Ignoring max_latency %u.\n", max_latency);
3734 
3735  return S_OK;
3736 }
3737 
3738 static HRESULT WINAPI d3d9_device_GetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT *max_latency)
3739 {
3740  FIXME("iface %p, max_latency %p stub!\n", iface, max_latency);
3741 
3742  *max_latency = 2;
3743 
3744  return E_NOTIMPL;
3745 }
3746 
3747 static HRESULT WINAPI d3d9_device_CheckDeviceState(IDirect3DDevice9Ex *iface, HWND dst_window)
3748 {
3750  struct wined3d_swapchain_desc swapchain_desc;
3751 
3752  TRACE("iface %p, dst_window %p.\n", iface, dst_window);
3753 
3755  wined3d_swapchain_get_desc(device->implicit_swapchains[0]->wined3d_swapchain, &swapchain_desc);
3757 
3758  if (swapchain_desc.windowed)
3759  return D3D_OK;
3760 
3761  /* FIXME: This is actually supposed to check if any other device is in
3762  * fullscreen mode. */
3763  if (dst_window != swapchain_desc.device_window)
3764  return device->device_state == D3D9_DEVICE_STATE_OK ? S_PRESENT_OCCLUDED : D3D_OK;
3765 
3766  return device->device_state == D3D9_DEVICE_STATE_OK ? D3D_OK : S_PRESENT_OCCLUDED;
3767 }
3768 
3769 static HRESULT WINAPI d3d9_device_CreateRenderTargetEx(IDirect3DDevice9Ex *iface,
3771  BOOL lockable, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage)
3772 {
3773  FIXME("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u, "
3774  "lockable %#x, surface %p, shared_handle %p, usage %#x stub!\n",
3776  lockable, surface, shared_handle, usage);
3777 
3778  *surface = NULL;
3779  if (shared_handle)
3780  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
3781 
3782  return E_NOTIMPL;
3783 }
3784 
3786  UINT width, UINT height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface,
3787  HANDLE *shared_handle, DWORD usage)
3788 {
3789  FIXME("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p, usage %#x stub!\n",
3790  iface, width, height, format, pool, surface, shared_handle, usage);
3791 
3792  return E_NOTIMPL;
3793 }
3794 
3795 static HRESULT WINAPI d3d9_device_CreateDepthStencilSurfaceEx(IDirect3DDevice9Ex *iface,
3797  BOOL discard, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage)
3798 {
3801 
3802  TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u, "
3803  "discard %#x, surface %p, shared_handle %p, usage %#x.\n",
3804  iface, width, height, format, multisample_type, multisample_quality,
3805  discard, surface, shared_handle, usage);
3806 
3808  {
3809  WARN("Invalid usage %#x.\n", usage);
3810  return D3DERR_INVALIDCALL;
3811  }
3812 
3813  if (shared_handle)
3814  FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
3815 
3816  if (discard)
3818 
3819  *surface = NULL;
3821  D3DUSAGE_DEPTHSTENCIL | usage, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL);
3822 }
3823 
3824 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_ResetEx(IDirect3DDevice9Ex *iface,
3825  D3DPRESENT_PARAMETERS *present_parameters, D3DDISPLAYMODEEX *mode)
3826 {
3828 
3829  TRACE("iface %p, present_parameters %p, mode %p.\n", iface, present_parameters, mode);
3830 
3831  if (!present_parameters->Windowed == !mode)
3832  {
3833  WARN("Mode can be passed if and only if Windowed is FALSE.\n");
3834  return D3DERR_INVALIDCALL;
3835  }
3836 
3837  if (mode && (mode->Width != present_parameters->BackBufferWidth
3838  || mode->Height != present_parameters->BackBufferHeight))
3839  {
3840  WARN("Mode and back buffer mismatch (mode %ux%u, backbuffer %ux%u).\n",
3841  mode->Width, mode->Height,
3842  present_parameters->BackBufferWidth, present_parameters->BackBufferHeight);
3843  return D3DERR_INVALIDCALL;
3844  }
3845 
3846  return d3d9_device_reset(device, present_parameters, mode);
3847 }
3848 
3849 static HRESULT WINAPI d3d9_device_GetDisplayModeEx(IDirect3DDevice9Ex *iface,
3850  UINT swapchain_idx, D3DDISPLAYMODEEX *mode, D3DDISPLAYROTATION *rotation)
3851 {
3853  struct wined3d_display_mode wined3d_mode;
3854  HRESULT hr;
3855 
3856  TRACE("iface %p, swapchain_idx %u, mode %p, rotation %p.\n",
3857  iface, swapchain_idx, mode, rotation);
3858 
3859  if (mode->Size != sizeof(*mode))
3860  return D3DERR_INVALIDCALL;
3861 
3863  hr = wined3d_device_get_display_mode(device->wined3d_device, swapchain_idx, &wined3d_mode,
3864  (enum wined3d_display_rotation *)rotation);
3866 
3867  if (SUCCEEDED(hr))
3868  {
3869  mode->Width = wined3d_mode.width;
3870  mode->Height = wined3d_mode.height;
3871  mode->RefreshRate = wined3d_mode.refresh_rate;
3872  mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
3873  mode->ScanLineOrdering = wined3d_mode.scanline_ordering;
3874  }
3875 
3876  return hr;
3877 }
3878 
3879 static const struct IDirect3DDevice9ExVtbl d3d9_device_vtbl =
3880 {
3881  /* IUnknown */
3885  /* IDirect3DDevice9 */
4002  /* IDirect3DDevice9Ex */
4018 };
4019 
4021 {
4023 }
4024 
4026  struct wined3d_device *device)
4027 {
4028  TRACE("device_parent %p, device %p.\n", device_parent, device);
4029 }
4030 
4032 {
4033  TRACE("device_parent %p.\n", device_parent);
4034 }
4035 
4037 {
4039 
4040  TRACE("device_parent %p, activate %#x.\n", device_parent, activate);
4041 
4042  if (!device->d3d_parent)
4043  return;
4044 
4045  if (!activate)
4047  else if (device->d3d_parent->extended)
4049  else
4051 }
4052 
4054  struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
4055  void **parent,