st/nine: clean device9ex.
[mesa.git] / src / gallium / state_trackers / nine / device9.c
1 /*
2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
23 #include "device9.h"
24 #include "stateblock9.h"
25 #include "surface9.h"
26 #include "swapchain9.h"
27 #include "swapchain9ex.h"
28 #include "indexbuffer9.h"
29 #include "vertexbuffer9.h"
30 #include "vertexdeclaration9.h"
31 #include "vertexshader9.h"
32 #include "pixelshader9.h"
33 #include "query9.h"
34 #include "texture9.h"
35 #include "cubetexture9.h"
36 #include "volumetexture9.h"
37 #include "nine_helpers.h"
38 #include "nine_pipe.h"
39 #include "nine_ff.h"
40 #include "nine_dump.h"
41
42 #include "pipe/p_screen.h"
43 #include "pipe/p_context.h"
44 #include "util/u_math.h"
45 #include "util/u_inlines.h"
46 #include "util/u_hash_table.h"
47 #include "util/u_format.h"
48 #include "util/u_surface.h"
49 #include "util/u_upload_mgr.h"
50 #include "hud/hud_context.h"
51
52 #include "cso_cache/cso_context.h"
53
54 #define DBG_CHANNEL DBG_DEVICE
55
56 static void
57 NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset )
58 {
59 struct NineSurface9 *refSurf = NULL;
60
61 assert(!This->is_recording);
62
63 nine_state_set_defaults(&This->state, &This->caps, is_reset);
64
65 This->state.viewport.X = 0;
66 This->state.viewport.Y = 0;
67 This->state.viewport.Width = 0;
68 This->state.viewport.Height = 0;
69
70 This->state.scissor.minx = 0;
71 This->state.scissor.miny = 0;
72 This->state.scissor.maxx = 0xffff;
73 This->state.scissor.maxy = 0xffff;
74
75 if (This->nswapchains && This->swapchains[0]->params.BackBufferCount)
76 refSurf = This->swapchains[0]->buffers[0];
77
78 if (refSurf) {
79 This->state.viewport.Width = refSurf->desc.Width;
80 This->state.viewport.Height = refSurf->desc.Height;
81 This->state.scissor.maxx = refSurf->desc.Width;
82 This->state.scissor.maxy = refSurf->desc.Height;
83 }
84
85 if (This->nswapchains && This->swapchains[0]->params.EnableAutoDepthStencil)
86 This->state.rs[D3DRS_ZENABLE] = TRUE;
87 if (This->state.rs[D3DRS_ZENABLE])
88 NineDevice9_SetDepthStencilSurface(
89 This, (IDirect3DSurface9 *)This->swapchains[0]->zsbuf);
90 }
91
92 void
93 NineDevice9_RestoreNonCSOState( struct NineDevice9 *This, unsigned mask )
94 {
95 struct pipe_context *pipe = This->pipe;
96
97 if (mask & 0x1) {
98 struct pipe_constant_buffer cb;
99 cb.buffer_offset = 0;
100
101 if (This->prefer_user_constbuf) {
102 cb.buffer = NULL;
103 cb.user_buffer = This->state.vs_const_f;
104 } else {
105 cb.buffer = This->constbuf_vs;
106 cb.user_buffer = NULL;
107 }
108 cb.buffer_size = This->constbuf_vs->width0;
109 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &cb);
110
111 if (This->prefer_user_constbuf) {
112 cb.user_buffer = This->state.ps_const_f;
113 } else {
114 cb.buffer = This->constbuf_ps;
115 }
116 cb.buffer_size = This->constbuf_ps->width0;
117 pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &cb);
118 }
119
120 if (mask & 0x2) {
121 struct pipe_poly_stipple stipple;
122 memset(&stipple, ~0, sizeof(stipple));
123 pipe->set_polygon_stipple(pipe, &stipple);
124 }
125
126 This->state.changed.group = NINE_STATE_ALL;
127 This->state.changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1;
128 This->state.changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
129 This->state.changed.texture = NINE_PS_SAMPLERS_MASK | NINE_VS_SAMPLERS_MASK;
130 }
131
132 #define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n)
133 HRESULT
134 NineDevice9_ctor( struct NineDevice9 *This,
135 struct NineUnknownParams *pParams,
136 struct pipe_screen *pScreen,
137 D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
138 D3DCAPS9 *pCaps,
139 D3DPRESENT_PARAMETERS *pPresentationParameters,
140 IDirect3D9 *pD3D9,
141 ID3DPresentGroup *pPresentationGroup,
142 struct d3dadapter9_context *pCTX,
143 boolean ex,
144 D3DDISPLAYMODEEX *pFullscreenDisplayMode )
145 {
146 unsigned i;
147 HRESULT hr = NineUnknown_ctor(&This->base, pParams);
148 if (FAILED(hr)) { return hr; }
149
150 list_inithead(&This->update_textures);
151
152 This->screen = pScreen;
153 This->caps = *pCaps;
154 This->d3d9 = pD3D9;
155 This->params = *pCreationParameters;
156 This->ex = ex;
157 This->present = pPresentationGroup;
158 IDirect3D9_AddRef(This->d3d9);
159 ID3DPresentGroup_AddRef(This->present);
160
161 This->pipe = This->screen->context_create(This->screen, NULL);
162 if (!This->pipe) { return E_OUTOFMEMORY; } /* guess */
163
164 This->cso = cso_create_context(This->pipe);
165 if (!This->cso) { return E_OUTOFMEMORY; } /* also a guess */
166
167 /* Create first, it messes up our state. */
168 This->hud = hud_create(This->pipe, This->cso); /* NULL result is fine */
169
170 /* create implicit swapchains */
171 This->nswapchains = ID3DPresentGroup_GetMultiheadCount(This->present);
172 This->swapchains = CALLOC(This->nswapchains,
173 sizeof(struct NineSwapChain9 *));
174 if (!This->swapchains) { return E_OUTOFMEMORY; }
175
176 for (i = 0; i < This->nswapchains; ++i) {
177 ID3DPresent *present;
178
179 hr = ID3DPresentGroup_GetPresent(This->present, i, &present);
180 if (FAILED(hr))
181 return hr;
182
183 if (ex) {
184 D3DDISPLAYMODEEX *mode = NULL;
185 struct NineSwapChain9Ex **ret =
186 (struct NineSwapChain9Ex **)&This->swapchains[i];
187
188 if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]);
189 /* when this is a Device9Ex, it should create SwapChain9Exs */
190 hr = NineSwapChain9Ex_new(This, TRUE, present,
191 &pPresentationParameters[i], pCTX,
192 This->params.hFocusWindow, mode, ret);
193 } else {
194 hr = NineSwapChain9_new(This, TRUE, present,
195 &pPresentationParameters[i], pCTX,
196 This->params.hFocusWindow,
197 &This->swapchains[i]);
198 }
199
200 ID3DPresent_Release(present);
201 if (FAILED(hr))
202 return hr;
203 NineUnknown_ConvertRefToBind(NineUnknown(This->swapchains[i]));
204
205 hr = NineSwapChain9_GetBackBuffer(This->swapchains[i], 0,
206 D3DBACKBUFFER_TYPE_MONO,
207 (IDirect3DSurface9 **)
208 &This->state.rt[i]);
209 if (FAILED(hr))
210 return hr;
211 NineUnknown_ConvertRefToBind(NineUnknown(This->state.rt[i]));
212 }
213
214 This->cursor.software = FALSE;
215 This->cursor.hotspot.x = -1;
216 This->cursor.hotspot.y = -1;
217 {
218 struct pipe_resource tmpl;
219 tmpl.target = PIPE_TEXTURE_2D;
220 tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM;
221 tmpl.width0 = 64;
222 tmpl.height0 = 64;
223 tmpl.depth0 = 1;
224 tmpl.array_size = 1;
225 tmpl.last_level = 0;
226 tmpl.nr_samples = 0;
227 tmpl.usage = PIPE_USAGE_DEFAULT;
228 tmpl.bind = PIPE_BIND_CURSOR | PIPE_BIND_SAMPLER_VIEW;
229 tmpl.flags = 0;
230
231 This->cursor.image = pScreen->resource_create(pScreen, &tmpl);
232 if (!This->cursor.image)
233 return D3DERR_OUTOFVIDEOMEMORY;
234 }
235
236 /* Create constant buffers. */
237 {
238 struct pipe_resource tmpl;
239 unsigned max_const_vs, max_const_ps;
240
241 max_const_vs = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX,
242 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) /
243 sizeof(float[4]),
244 NINE_MAX_CONST_ALL);
245 max_const_ps = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_FRAGMENT,
246 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) /
247 sizeof(float[4]),
248 NINE_MAX_CONST_ALL);
249
250 This->max_vs_const_f = max_const_vs -
251 (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);
252 This->max_ps_const_f = max_const_ps -
253 (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);
254
255 /* Include space for I,B constants for user constbuf. */
256 This->state.vs_const_f = CALLOC(NINE_MAX_CONST_ALL, sizeof(float[4]));
257 This->state.ps_const_f = CALLOC(NINE_MAX_CONST_ALL, sizeof(float[4]));
258 if (!This->state.vs_const_f || !This->state.ps_const_f)
259 return E_OUTOFMEMORY;
260
261 if (strstr(pScreen->get_name(pScreen), "AMD") ||
262 strstr(pScreen->get_name(pScreen), "ATI"))
263 This->prefer_user_constbuf = TRUE;
264
265 tmpl.target = PIPE_BUFFER;
266 tmpl.format = PIPE_FORMAT_R8_UNORM;
267 tmpl.height0 = 1;
268 tmpl.depth0 = 1;
269 tmpl.array_size = 1;
270 tmpl.last_level = 0;
271 tmpl.nr_samples = 0;
272 tmpl.usage = PIPE_USAGE_DYNAMIC;
273 tmpl.bind = PIPE_BIND_CONSTANT_BUFFER;
274 tmpl.flags = 0;
275
276 tmpl.width0 = max_const_vs * sizeof(float[4]);
277 This->constbuf_vs = pScreen->resource_create(pScreen, &tmpl);
278
279 tmpl.width0 = max_const_ps * sizeof(float[4]);
280 This->constbuf_ps = pScreen->resource_create(pScreen, &tmpl);
281
282 if (!This->constbuf_vs || !This->constbuf_ps)
283 return E_OUTOFMEMORY;
284 }
285
286 This->vs_bool_true = pScreen->get_shader_param(pScreen,
287 PIPE_SHADER_VERTEX,
288 PIPE_SHADER_CAP_INTEGERS) ? 0xFFFFFFFF : fui(1.0f);
289 This->ps_bool_true = pScreen->get_shader_param(pScreen,
290 PIPE_SHADER_FRAGMENT,
291 PIPE_SHADER_CAP_INTEGERS) ? 0xFFFFFFFF : fui(1.0f);
292
293 /* Allocate upload helper for drivers that suck (from st pov ;). */
294 {
295 unsigned bind = 0;
296
297 This->driver_caps.user_vbufs = GET_PCAP(USER_VERTEX_BUFFERS);
298 This->driver_caps.user_ibufs = GET_PCAP(USER_INDEX_BUFFERS);
299
300 if (!This->driver_caps.user_vbufs) bind |= PIPE_BIND_VERTEX_BUFFER;
301 if (!This->driver_caps.user_ibufs) bind |= PIPE_BIND_INDEX_BUFFER;
302 if (bind)
303 This->upload = u_upload_create(This->pipe, 1 << 20, 4, bind);
304 }
305
306 This->driver_caps.window_space_position_support = GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION);
307
308 nine_ff_init(This); /* initialize fixed function code */
309
310 NineDevice9_SetDefaultState(This, FALSE);
311 NineDevice9_RestoreNonCSOState(This, ~0);
312
313 This->update = &This->state;
314 nine_update_state(This, ~0);
315
316 ID3DPresentGroup_Release(This->present);
317
318 return D3D_OK;
319 }
320 #undef GET_PCAP
321
322 void
323 NineDevice9_dtor( struct NineDevice9 *This )
324 {
325 unsigned i;
326
327 DBG("This=%p\n", This);
328
329 if (This->pipe && This->cso)
330 nine_pipe_context_clear(This);
331 nine_ff_fini(This);
332 nine_state_clear(&This->state, TRUE);
333
334 if (This->upload)
335 u_upload_destroy(This->upload);
336
337 nine_bind(&This->record, NULL);
338
339 pipe_resource_reference(&This->constbuf_vs, NULL);
340 pipe_resource_reference(&This->constbuf_ps, NULL);
341 FREE(This->state.vs_const_f);
342 FREE(This->state.ps_const_f);
343
344 if (This->swapchains) {
345 for (i = 0; i < This->nswapchains; ++i)
346 NineUnknown_Unbind(NineUnknown(This->swapchains[i]));
347 FREE(This->swapchains);
348 }
349
350 /* state stuff */
351 if (This->pipe) {
352 if (This->cso) {
353 cso_release_all(This->cso);
354 cso_destroy_context(This->cso);
355 }
356 if (This->pipe->destroy) { This->pipe->destroy(This->pipe); }
357 }
358
359 if (This->present) { ID3DPresentGroup_Release(This->present); }
360 if (This->d3d9) { IDirect3D9_Release(This->d3d9); }
361
362 NineUnknown_dtor(&This->base);
363 }
364
365 struct pipe_screen *
366 NineDevice9_GetScreen( struct NineDevice9 *This )
367 {
368 return This->screen;
369 }
370
371 struct pipe_context *
372 NineDevice9_GetPipe( struct NineDevice9 *This )
373 {
374 return This->pipe;
375 }
376
377 struct cso_context *
378 NineDevice9_GetCSO( struct NineDevice9 *This )
379 {
380 return This->cso;
381 }
382
383 const D3DCAPS9 *
384 NineDevice9_GetCaps( struct NineDevice9 *This )
385 {
386 return &This->caps;
387 }
388
389 static INLINE void
390 NineDevice9_PauseRecording( struct NineDevice9 *This )
391 {
392 if (This->record) {
393 This->update = &This->state;
394 This->is_recording = FALSE;
395 }
396 }
397
398 static INLINE void
399 NineDevice9_ResumeRecording( struct NineDevice9 *This )
400 {
401 if (This->record) {
402 This->update = &This->record->state;
403 This->is_recording = TRUE;
404 }
405 }
406
407 HRESULT WINAPI
408 NineDevice9_TestCooperativeLevel( struct NineDevice9 *This )
409 {
410 return D3D_OK; /* TODO */
411 }
412
413 UINT WINAPI
414 NineDevice9_GetAvailableTextureMem( struct NineDevice9 *This )
415 {
416 return This->screen->get_param(This->screen, PIPE_CAP_VIDEO_MEMORY);
417 }
418
419 HRESULT WINAPI
420 NineDevice9_EvictManagedResources( struct NineDevice9 *This )
421 {
422 /* We don't really need to do anything here, but might want to free up
423 * the GPU virtual address space by killing pipe_resources.
424 */
425 STUB(D3D_OK);
426 }
427
428 HRESULT WINAPI
429 NineDevice9_GetDirect3D( struct NineDevice9 *This,
430 IDirect3D9 **ppD3D9 )
431 {
432 user_assert(ppD3D9 != NULL, E_POINTER);
433 IDirect3D9_AddRef(This->d3d9);
434 *ppD3D9 = This->d3d9;
435 return D3D_OK;
436 }
437
438 HRESULT WINAPI
439 NineDevice9_GetDeviceCaps( struct NineDevice9 *This,
440 D3DCAPS9 *pCaps )
441 {
442 user_assert(pCaps != NULL, D3DERR_INVALIDCALL);
443 *pCaps = This->caps;
444 return D3D_OK;
445 }
446
447 HRESULT WINAPI
448 NineDevice9_GetDisplayMode( struct NineDevice9 *This,
449 UINT iSwapChain,
450 D3DDISPLAYMODE *pMode )
451 {
452 DBG("This=%p iSwapChain=%u pMode=%p\n", This, iSwapChain, pMode);
453
454 user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
455
456 return NineSwapChain9_GetDisplayMode(This->swapchains[iSwapChain], pMode);
457 }
458
459 HRESULT WINAPI
460 NineDevice9_GetCreationParameters( struct NineDevice9 *This,
461 D3DDEVICE_CREATION_PARAMETERS *pParameters )
462 {
463 user_assert(pParameters != NULL, D3DERR_INVALIDCALL);
464 *pParameters = This->params;
465 return D3D_OK;
466 }
467
468 HRESULT WINAPI
469 NineDevice9_SetCursorProperties( struct NineDevice9 *This,
470 UINT XHotSpot,
471 UINT YHotSpot,
472 IDirect3DSurface9 *pCursorBitmap )
473 {
474 /* TODO: hardware cursor */
475 struct NineSurface9 *surf = NineSurface9(pCursorBitmap);
476 struct pipe_context *pipe = This->pipe;
477 struct pipe_box box;
478 struct pipe_transfer *transfer;
479 void *ptr;
480
481 DBG_FLAG(DBG_SWAPCHAIN, "This=%p XHotSpot=%u YHotSpot=%u "
482 "pCursorBitmap=%p\n", This, XHotSpot, YHotSpot, pCursorBitmap);
483
484 user_assert(pCursorBitmap, D3DERR_INVALIDCALL);
485
486 This->cursor.w = MIN2(surf->desc.Width, This->cursor.image->width0);
487 This->cursor.h = MIN2(surf->desc.Height, This->cursor.image->height0);
488
489 u_box_origin_2d(This->cursor.w, This->cursor.h, &box);
490
491 ptr = pipe->transfer_map(pipe, This->cursor.image, 0,
492 PIPE_TRANSFER_WRITE |
493 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
494 &box, &transfer);
495 if (!ptr)
496 ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR);
497
498 This->cursor.hotspot.x = XHotSpot;
499 This->cursor.hotspot.y = YHotSpot;
500
501 /* Copy cursor image to internal storage. */
502 {
503 D3DLOCKED_RECT lock;
504 HRESULT hr;
505 const struct util_format_description *sfmt =
506 util_format_description(surf->base.info.format);
507 assert(sfmt);
508
509 hr = NineSurface9_LockRect(surf, &lock, NULL, D3DLOCK_READONLY);
510 if (FAILED(hr))
511 ret_err("Failed to map cursor source image.\n",
512 D3DERR_DRIVERINTERNALERROR);
513
514 sfmt->unpack_rgba_8unorm(ptr, transfer->stride,
515 lock.pBits, lock.Pitch,
516 This->cursor.w, This->cursor.h);
517
518 if (!This->cursor.software &&
519 This->cursor.w == 32 && This->cursor.h == 32)
520 ID3DPresent_SetCursor(This->swapchains[0]->present,
521 lock.pBits, &This->cursor.hotspot,
522 This->cursor.visible);
523
524 NineSurface9_UnlockRect(surf);
525 }
526 pipe->transfer_unmap(pipe, transfer);
527
528 return D3D_OK;
529 }
530
531 void WINAPI
532 NineDevice9_SetCursorPosition( struct NineDevice9 *This,
533 int X,
534 int Y,
535 DWORD Flags )
536 {
537 struct NineSwapChain9 *swap = This->swapchains[0];
538
539 This->cursor.pos.x = X;
540 This->cursor.pos.y = Y;
541
542 if (!This->cursor.software)
543 ID3DPresent_SetCursorPos(swap->present, &This->cursor.pos);
544 }
545
546 BOOL WINAPI
547 NineDevice9_ShowCursor( struct NineDevice9 *This,
548 BOOL bShow )
549 {
550 BOOL old = This->cursor.visible;
551 This->cursor.visible = bShow && (This->cursor.hotspot.x != -1);
552 if (!This->cursor.software)
553 ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow);
554
555 return old;
556 }
557
558 HRESULT WINAPI
559 NineDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This,
560 D3DPRESENT_PARAMETERS *pPresentationParameters,
561 IDirect3DSwapChain9 **pSwapChain )
562 {
563 struct NineSwapChain9 *swapchain, *tmplt = This->swapchains[0];
564 ID3DPresent *present;
565 HRESULT hr;
566
567 user_assert(pPresentationParameters, D3DERR_INVALIDCALL);
568
569 hr = ID3DPresentGroup_CreateAdditionalPresent(This->present, pPresentationParameters, &present);
570
571 if (FAILED(hr))
572 return hr;
573
574 hr = NineSwapChain9_new(This, FALSE, present, pPresentationParameters,
575 tmplt->actx,
576 tmplt->params.hDeviceWindow,
577 &swapchain);
578 if (FAILED(hr))
579 return hr;
580
581 *pSwapChain = (IDirect3DSwapChain9 *)swapchain;
582 return D3D_OK;
583 }
584
585 HRESULT WINAPI
586 NineDevice9_GetSwapChain( struct NineDevice9 *This,
587 UINT iSwapChain,
588 IDirect3DSwapChain9 **pSwapChain )
589 {
590 user_assert(pSwapChain != NULL, D3DERR_INVALIDCALL);
591
592 *pSwapChain = NULL;
593 user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
594
595 NineUnknown_AddRef(NineUnknown(This->swapchains[iSwapChain]));
596 *pSwapChain = (IDirect3DSwapChain9 *)This->swapchains[iSwapChain];
597
598 return D3D_OK;
599 }
600
601 UINT WINAPI
602 NineDevice9_GetNumberOfSwapChains( struct NineDevice9 *This )
603 {
604 return This->nswapchains;
605 }
606
607 HRESULT WINAPI
608 NineDevice9_Reset( struct NineDevice9 *This,
609 D3DPRESENT_PARAMETERS *pPresentationParameters )
610 {
611 HRESULT hr = D3D_OK;
612 unsigned i;
613
614 DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters);
615
616 for (i = 0; i < This->nswapchains; ++i) {
617 D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i];
618 hr = NineSwapChain9_Resize(This->swapchains[i], params, NULL);
619 if (FAILED(hr))
620 return (hr == D3DERR_OUTOFVIDEOMEMORY) ? hr : D3DERR_DEVICELOST;
621 }
622
623 nine_pipe_context_clear(This);
624 nine_state_clear(&This->state, TRUE);
625
626 NineDevice9_SetDefaultState(This, TRUE);
627 NineDevice9_SetRenderTarget(
628 This, 0, (IDirect3DSurface9 *)This->swapchains[0]->buffers[0]);
629 /* XXX: better use GetBackBuffer here ? */
630
631 return hr;
632 }
633
634 HRESULT WINAPI
635 NineDevice9_Present( struct NineDevice9 *This,
636 const RECT *pSourceRect,
637 const RECT *pDestRect,
638 HWND hDestWindowOverride,
639 const RGNDATA *pDirtyRegion )
640 {
641 unsigned i;
642 HRESULT hr;
643
644 /* XXX is this right? */
645 for (i = 0; i < This->nswapchains; ++i) {
646 hr = NineSwapChain9_Present(This->swapchains[i], pSourceRect, pDestRect,
647 hDestWindowOverride, pDirtyRegion, 0);
648 if (FAILED(hr)) { return hr; }
649 }
650
651 return D3D_OK;
652 }
653
654 HRESULT WINAPI
655 NineDevice9_GetBackBuffer( struct NineDevice9 *This,
656 UINT iSwapChain,
657 UINT iBackBuffer,
658 D3DBACKBUFFER_TYPE Type,
659 IDirect3DSurface9 **ppBackBuffer )
660 {
661 user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL);
662 user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
663
664 return NineSwapChain9_GetBackBuffer(This->swapchains[iSwapChain],
665 iBackBuffer, Type, ppBackBuffer);
666 }
667
668 HRESULT WINAPI
669 NineDevice9_GetRasterStatus( struct NineDevice9 *This,
670 UINT iSwapChain,
671 D3DRASTER_STATUS *pRasterStatus )
672 {
673 user_assert(pRasterStatus != NULL, D3DERR_INVALIDCALL);
674 user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
675
676 return NineSwapChain9_GetRasterStatus(This->swapchains[iSwapChain],
677 pRasterStatus);
678 }
679
680 HRESULT WINAPI
681 NineDevice9_SetDialogBoxMode( struct NineDevice9 *This,
682 BOOL bEnableDialogs )
683 {
684 STUB(D3DERR_INVALIDCALL);
685 }
686
687 void WINAPI
688 NineDevice9_SetGammaRamp( struct NineDevice9 *This,
689 UINT iSwapChain,
690 DWORD Flags,
691 const D3DGAMMARAMP *pRamp )
692 {
693 DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This,
694 iSwapChain, Flags, pRamp);
695
696 user_warn(iSwapChain >= This->nswapchains);
697 user_warn(!pRamp);
698
699 if (pRamp && (iSwapChain < This->nswapchains)) {
700 struct NineSwapChain9 *swap = This->swapchains[iSwapChain];
701 swap->gamma = *pRamp;
702 ID3DPresent_SetGammaRamp(swap->present, pRamp, swap->params.hDeviceWindow);
703 }
704 }
705
706 void WINAPI
707 NineDevice9_GetGammaRamp( struct NineDevice9 *This,
708 UINT iSwapChain,
709 D3DGAMMARAMP *pRamp )
710 {
711 DBG("This=%p iSwapChain=%u pRamp=%p\n", This, iSwapChain, pRamp);
712
713 user_warn(iSwapChain >= This->nswapchains);
714 user_warn(!pRamp);
715
716 if (pRamp && (iSwapChain < This->nswapchains))
717 *pRamp = This->swapchains[iSwapChain]->gamma;
718 }
719
720 HRESULT WINAPI
721 NineDevice9_CreateTexture( struct NineDevice9 *This,
722 UINT Width,
723 UINT Height,
724 UINT Levels,
725 DWORD Usage,
726 D3DFORMAT Format,
727 D3DPOOL Pool,
728 IDirect3DTexture9 **ppTexture,
729 HANDLE *pSharedHandle )
730 {
731 struct NineTexture9 *tex;
732 HRESULT hr;
733
734 DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s "
735 "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Levels,
736 nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),
737 nine_D3DPOOL_to_str(Pool), ppTexture, pSharedHandle);
738
739 Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DMAP |
740 D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET |
741 D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI;
742
743 user_assert(Width && Height, D3DERR_INVALIDCALL);
744 user_assert(!pSharedHandle || This->ex, D3DERR_INVALIDCALL);
745 /* When is used shared handle, Pool must be
746 * SYSTEMMEM with Levels 1 or DEFAULT with any Levels */
747 user_assert(!pSharedHandle || Pool != D3DPOOL_SYSTEMMEM || Levels == 1,
748 D3DERR_INVALIDCALL);
749 user_assert(!pSharedHandle || Pool == D3DPOOL_SYSTEMMEM || Pool == D3DPOOL_DEFAULT,
750 D3DERR_INVALIDCALL);
751 user_assert((Usage != D3DUSAGE_AUTOGENMIPMAP || Levels <= 1), D3DERR_INVALIDCALL);
752
753 hr = NineTexture9_new(This, Width, Height, Levels, Usage, Format, Pool,
754 &tex, pSharedHandle);
755 if (SUCCEEDED(hr))
756 *ppTexture = (IDirect3DTexture9 *)tex;
757
758 return hr;
759 }
760
761 HRESULT WINAPI
762 NineDevice9_CreateVolumeTexture( struct NineDevice9 *This,
763 UINT Width,
764 UINT Height,
765 UINT Depth,
766 UINT Levels,
767 DWORD Usage,
768 D3DFORMAT Format,
769 D3DPOOL Pool,
770 IDirect3DVolumeTexture9 **ppVolumeTexture,
771 HANDLE *pSharedHandle )
772 {
773 struct NineVolumeTexture9 *tex;
774 HRESULT hr;
775
776 DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s "
777 "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Depth, Levels,
778 nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),
779 nine_D3DPOOL_to_str(Pool), ppVolumeTexture, pSharedHandle);
780
781 Usage &= D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |
782 D3DUSAGE_SOFTWAREPROCESSING;
783
784 user_assert(Width && Height && Depth, D3DERR_INVALIDCALL);
785 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
786
787 hr = NineVolumeTexture9_new(This, Width, Height, Depth, Levels,
788 Usage, Format, Pool, &tex, pSharedHandle);
789 if (SUCCEEDED(hr))
790 *ppVolumeTexture = (IDirect3DVolumeTexture9 *)tex;
791
792 return hr;
793 }
794
795 HRESULT WINAPI
796 NineDevice9_CreateCubeTexture( struct NineDevice9 *This,
797 UINT EdgeLength,
798 UINT Levels,
799 DWORD Usage,
800 D3DFORMAT Format,
801 D3DPOOL Pool,
802 IDirect3DCubeTexture9 **ppCubeTexture,
803 HANDLE *pSharedHandle )
804 {
805 struct NineCubeTexture9 *tex;
806 HRESULT hr;
807
808 DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p "
809 "pSharedHandle=%p\n", This, EdgeLength, Levels,
810 nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),
811 nine_D3DPOOL_to_str(Pool), ppCubeTexture, pSharedHandle);
812
813 Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DYNAMIC |
814 D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET |
815 D3DUSAGE_SOFTWAREPROCESSING;
816
817 user_assert(EdgeLength, D3DERR_INVALIDCALL);
818 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
819
820 hr = NineCubeTexture9_new(This, EdgeLength, Levels, Usage, Format, Pool,
821 &tex, pSharedHandle);
822 if (SUCCEEDED(hr))
823 *ppCubeTexture = (IDirect3DCubeTexture9 *)tex;
824
825 return hr;
826 }
827
828 HRESULT WINAPI
829 NineDevice9_CreateVertexBuffer( struct NineDevice9 *This,
830 UINT Length,
831 DWORD Usage,
832 DWORD FVF,
833 D3DPOOL Pool,
834 IDirect3DVertexBuffer9 **ppVertexBuffer,
835 HANDLE *pSharedHandle )
836 {
837 struct NineVertexBuffer9 *buf;
838 HRESULT hr;
839 D3DVERTEXBUFFER_DESC desc;
840
841 DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n",
842 This, Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle);
843
844 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE);
845
846 desc.Format = D3DFMT_VERTEXDATA;
847 desc.Type = D3DRTYPE_VERTEXBUFFER;
848 desc.Usage = Usage &
849 (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |
850 D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES |
851 D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI |
852 D3DUSAGE_WRITEONLY);
853 desc.Pool = Pool;
854 desc.Size = Length;
855 desc.FVF = FVF;
856
857 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
858 user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL);
859
860 hr = NineVertexBuffer9_new(This, &desc, &buf);
861 if (SUCCEEDED(hr))
862 *ppVertexBuffer = (IDirect3DVertexBuffer9 *)buf;
863 return hr;
864 }
865
866 HRESULT WINAPI
867 NineDevice9_CreateIndexBuffer( struct NineDevice9 *This,
868 UINT Length,
869 DWORD Usage,
870 D3DFORMAT Format,
871 D3DPOOL Pool,
872 IDirect3DIndexBuffer9 **ppIndexBuffer,
873 HANDLE *pSharedHandle )
874 {
875 struct NineIndexBuffer9 *buf;
876 HRESULT hr;
877 D3DINDEXBUFFER_DESC desc;
878
879 DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p "
880 "pSharedHandle=%p\n", This, Length, Usage,
881 d3dformat_to_string(Format), Pool, ppIndexBuffer, pSharedHandle);
882
883 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE);
884
885 desc.Format = Format;
886 desc.Type = D3DRTYPE_INDEXBUFFER;
887 desc.Usage = Usage &
888 (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |
889 D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES |
890 D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY);
891 desc.Pool = Pool;
892 desc.Size = Length;
893
894 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
895 user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL);
896
897 hr = NineIndexBuffer9_new(This, &desc, &buf);
898 if (SUCCEEDED(hr))
899 *ppIndexBuffer = (IDirect3DIndexBuffer9 *)buf;
900 return hr;
901 }
902
903 static HRESULT
904 create_zs_or_rt_surface(struct NineDevice9 *This,
905 unsigned type, /* 0 = RT, 1 = ZS, 2 = plain */
906 D3DPOOL Pool,
907 UINT Width, UINT Height,
908 D3DFORMAT Format,
909 D3DMULTISAMPLE_TYPE MultiSample,
910 DWORD MultisampleQuality,
911 BOOL Discard_or_Lockable,
912 IDirect3DSurface9 **ppSurface,
913 HANDLE *pSharedHandle)
914 {
915 struct NineSurface9 *surface;
916 struct pipe_screen *screen = This->screen;
917 struct pipe_resource *resource = NULL;
918 HRESULT hr;
919 D3DSURFACE_DESC desc;
920 struct pipe_resource templ;
921
922 DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u "
923 "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n",
924 This, type, nine_D3DPOOL_to_str(Pool), Width, Height,
925 d3dformat_to_string(Format), MultiSample, MultisampleQuality,
926 Discard_or_Lockable, ppSurface, pSharedHandle);
927
928 if (pSharedHandle)
929 DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n");
930
931 user_assert(Width && Height, D3DERR_INVALIDCALL);
932 user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL);
933
934 templ.target = PIPE_TEXTURE_2D;
935 templ.format = d3d9_to_pipe_format(Format);
936 templ.width0 = Width;
937 templ.height0 = Height;
938 templ.depth0 = 1;
939 templ.array_size = 1;
940 templ.last_level = 0;
941 templ.nr_samples = (unsigned)MultiSample;
942 templ.usage = PIPE_USAGE_DEFAULT;
943 templ.flags = 0;
944 templ.bind = PIPE_BIND_SAMPLER_VIEW; /* StretchRect */
945 switch (type) {
946 case 0: templ.bind |= PIPE_BIND_RENDER_TARGET; break;
947 case 1: templ.bind |= PIPE_BIND_DEPTH_STENCIL; break;
948 default:
949 assert(type == 2);
950 break;
951 }
952
953 desc.Format = Format;
954 desc.Type = D3DRTYPE_SURFACE;
955 desc.Usage = 0;
956 desc.Pool = Pool;
957 desc.MultiSampleType = MultiSample;
958 desc.MultiSampleQuality = MultisampleQuality;
959 desc.Width = Width;
960 desc.Height = Height;
961 switch (type) {
962 case 0: desc.Usage = D3DUSAGE_RENDERTARGET; break;
963 case 1: desc.Usage = D3DUSAGE_DEPTHSTENCIL; break;
964 default: break;
965 }
966
967 if (Pool == D3DPOOL_DEFAULT && Format != D3DFMT_NULL) {
968 /* resource_create doesn't return an error code, so check format here */
969 user_assert(CHECK_PIPE_RESOURCE_TEMPLATE(templ), D3DERR_INVALIDCALL);
970 resource = screen->resource_create(screen, &templ);
971 user_assert(resource, D3DERR_OUTOFVIDEOMEMORY);
972 if (Discard_or_Lockable && (desc.Usage & D3DUSAGE_RENDERTARGET))
973 resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
974 } else {
975 resource = NULL;
976 }
977 hr = NineSurface9_new(This, NULL, resource, NULL, 0, 0, 0, &desc, &surface);
978 pipe_resource_reference(&resource, NULL);
979
980 if (SUCCEEDED(hr))
981 *ppSurface = (IDirect3DSurface9 *)surface;
982 return hr;
983 }
984
985 HRESULT WINAPI
986 NineDevice9_CreateRenderTarget( struct NineDevice9 *This,
987 UINT Width,
988 UINT Height,
989 D3DFORMAT Format,
990 D3DMULTISAMPLE_TYPE MultiSample,
991 DWORD MultisampleQuality,
992 BOOL Lockable,
993 IDirect3DSurface9 **ppSurface,
994 HANDLE *pSharedHandle )
995 {
996 return create_zs_or_rt_surface(This, 0, D3DPOOL_DEFAULT,
997 Width, Height, Format,
998 MultiSample, MultisampleQuality,
999 Lockable, ppSurface, pSharedHandle);
1000 }
1001
1002 HRESULT WINAPI
1003 NineDevice9_CreateDepthStencilSurface( struct NineDevice9 *This,
1004 UINT Width,
1005 UINT Height,
1006 D3DFORMAT Format,
1007 D3DMULTISAMPLE_TYPE MultiSample,
1008 DWORD MultisampleQuality,
1009 BOOL Discard,
1010 IDirect3DSurface9 **ppSurface,
1011 HANDLE *pSharedHandle )
1012 {
1013 return create_zs_or_rt_surface(This, 1, D3DPOOL_DEFAULT,
1014 Width, Height, Format,
1015 MultiSample, MultisampleQuality,
1016 Discard, ppSurface, pSharedHandle);
1017 }
1018
1019 HRESULT WINAPI
1020 NineDevice9_UpdateSurface( struct NineDevice9 *This,
1021 IDirect3DSurface9 *pSourceSurface,
1022 const RECT *pSourceRect,
1023 IDirect3DSurface9 *pDestinationSurface,
1024 const POINT *pDestPoint )
1025 {
1026 struct NineSurface9 *dst = NineSurface9(pDestinationSurface);
1027 struct NineSurface9 *src = NineSurface9(pSourceSurface);
1028
1029 DBG("This=%p pSourceSurface=%p pDestinationSurface=%p "
1030 "pSourceRect=%p pDestPoint=%p\n", This,
1031 pSourceSurface, pDestinationSurface, pSourceRect, pDestPoint);
1032 if (pSourceRect)
1033 DBG("pSourceRect = (%u,%u)-(%u,%u)\n",
1034 pSourceRect->left, pSourceRect->top,
1035 pSourceRect->right, pSourceRect->bottom);
1036 if (pDestPoint)
1037 DBG("pDestPoint = (%u,%u)\n", pDestPoint->x, pDestPoint->y);
1038
1039 user_assert(dst->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
1040 user_assert(src->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
1041
1042 user_assert(dst->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);
1043 user_assert(src->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);
1044
1045 return NineSurface9_CopySurface(dst, src, pDestPoint, pSourceRect);
1046 }
1047
1048 HRESULT WINAPI
1049 NineDevice9_UpdateTexture( struct NineDevice9 *This,
1050 IDirect3DBaseTexture9 *pSourceTexture,
1051 IDirect3DBaseTexture9 *pDestinationTexture )
1052 {
1053 struct NineBaseTexture9 *dstb = NineBaseTexture9(pDestinationTexture);
1054 struct NineBaseTexture9 *srcb = NineBaseTexture9(pSourceTexture);
1055 unsigned l, m;
1056 unsigned last_level = dstb->base.info.last_level;
1057
1058 DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This,
1059 pSourceTexture, pDestinationTexture);
1060
1061 user_assert(pSourceTexture != pDestinationTexture, D3DERR_INVALIDCALL);
1062
1063 user_assert(dstb->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
1064 user_assert(srcb->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
1065
1066 if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) {
1067 /* Only the first level is updated, the others regenerated. */
1068 last_level = 0;
1069 } else {
1070 user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP), D3DERR_INVALIDCALL);
1071 }
1072
1073 user_assert(dstb->base.type == srcb->base.type, D3DERR_INVALIDCALL);
1074
1075 /* TODO: We can restrict the update to the dirty portions of the source.
1076 * Yes, this seems silly, but it's what MSDN says ...
1077 */
1078
1079 /* Find src level that matches dst level 0: */
1080 user_assert(srcb->base.info.width0 >= dstb->base.info.width0 &&
1081 srcb->base.info.height0 >= dstb->base.info.height0 &&
1082 srcb->base.info.depth0 >= dstb->base.info.depth0,
1083 D3DERR_INVALIDCALL);
1084 for (m = 0; m <= srcb->base.info.last_level; ++m) {
1085 unsigned w = u_minify(srcb->base.info.width0, m);
1086 unsigned h = u_minify(srcb->base.info.height0, m);
1087 unsigned d = u_minify(srcb->base.info.depth0, m);
1088
1089 if (w == dstb->base.info.width0 &&
1090 h == dstb->base.info.height0 &&
1091 d == dstb->base.info.depth0)
1092 break;
1093 }
1094 user_assert(m <= srcb->base.info.last_level, D3DERR_INVALIDCALL);
1095
1096 last_level = MIN2(last_level, srcb->base.info.last_level - m);
1097
1098 if (dstb->base.type == D3DRTYPE_TEXTURE) {
1099 struct NineTexture9 *dst = NineTexture9(dstb);
1100 struct NineTexture9 *src = NineTexture9(srcb);
1101
1102 for (l = 0; l <= last_level; ++l, ++m)
1103 NineSurface9_CopySurface(dst->surfaces[l],
1104 src->surfaces[m], NULL, NULL);
1105 } else
1106 if (dstb->base.type == D3DRTYPE_CUBETEXTURE) {
1107 struct NineCubeTexture9 *dst = NineCubeTexture9(dstb);
1108 struct NineCubeTexture9 *src = NineCubeTexture9(srcb);
1109 unsigned z;
1110
1111 /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */
1112 for (z = 0; z < 6; ++z) {
1113 for (l = 0; l <= last_level; ++l, ++m) {
1114 NineSurface9_CopySurface(dst->surfaces[l * 6 + z],
1115 src->surfaces[m * 6 + z], NULL, NULL);
1116 }
1117 m -= l;
1118 }
1119 } else
1120 if (dstb->base.type == D3DRTYPE_VOLUMETEXTURE) {
1121 struct NineVolumeTexture9 *dst = NineVolumeTexture9(dstb);
1122 struct NineVolumeTexture9 *src = NineVolumeTexture9(srcb);
1123
1124 for (l = 0; l <= last_level; ++l, ++m)
1125 NineVolume9_CopyVolume(dst->volumes[l],
1126 src->volumes[m], 0, 0, 0, NULL);
1127 } else{
1128 assert(!"invalid texture type");
1129 }
1130
1131 if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP)
1132 NineBaseTexture9_GenerateMipSubLevels(dstb);
1133
1134 return D3D_OK;
1135 }
1136
1137 HRESULT WINAPI
1138 NineDevice9_GetRenderTargetData( struct NineDevice9 *This,
1139 IDirect3DSurface9 *pRenderTarget,
1140 IDirect3DSurface9 *pDestSurface )
1141 {
1142 struct NineSurface9 *dst = NineSurface9(pDestSurface);
1143 struct NineSurface9 *src = NineSurface9(pRenderTarget);
1144
1145 DBG("This=%p pRenderTarget=%p pDestSurface=%p\n",
1146 This, pRenderTarget, pDestSurface);
1147
1148 user_assert(dst->desc.Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
1149 user_assert(src->desc.Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
1150
1151 user_assert(dst->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);
1152 user_assert(src->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);
1153
1154 return NineSurface9_CopySurface(dst, src, NULL, NULL);
1155 }
1156
1157 HRESULT WINAPI
1158 NineDevice9_GetFrontBufferData( struct NineDevice9 *This,
1159 UINT iSwapChain,
1160 IDirect3DSurface9 *pDestSurface )
1161 {
1162 DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This,
1163 iSwapChain, pDestSurface);
1164
1165 user_assert(pDestSurface != NULL, D3DERR_INVALIDCALL);
1166 user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
1167
1168 return NineSwapChain9_GetFrontBufferData(This->swapchains[iSwapChain],
1169 pDestSurface);
1170 }
1171
1172 HRESULT WINAPI
1173 NineDevice9_StretchRect( struct NineDevice9 *This,
1174 IDirect3DSurface9 *pSourceSurface,
1175 const RECT *pSourceRect,
1176 IDirect3DSurface9 *pDestSurface,
1177 const RECT *pDestRect,
1178 D3DTEXTUREFILTERTYPE Filter )
1179 {
1180 struct pipe_screen *screen = This->screen;
1181 struct pipe_context *pipe = This->pipe;
1182 struct NineSurface9 *dst = NineSurface9(pDestSurface);
1183 struct NineSurface9 *src = NineSurface9(pSourceSurface);
1184 struct pipe_resource *dst_res = NineSurface9_GetResource(dst);
1185 struct pipe_resource *src_res = NineSurface9_GetResource(src);
1186 const boolean zs = util_format_is_depth_or_stencil(dst_res->format);
1187 struct pipe_blit_info blit;
1188 boolean scaled, clamped, ms, flip_x = FALSE, flip_y = FALSE;
1189
1190 DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p "
1191 "pDestRect=%p Filter=%u\n",
1192 This, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter);
1193 if (pSourceRect)
1194 DBG("pSourceRect=(%u,%u)-(%u,%u)\n",
1195 pSourceRect->left, pSourceRect->top,
1196 pSourceRect->right, pSourceRect->bottom);
1197 if (pDestRect)
1198 DBG("pSourceRect=(%u,%u)-(%u,%u)\n", pDestRect->left, pDestRect->top,
1199 pDestRect->right, pDestRect->bottom);
1200
1201 user_assert(!zs || !This->in_scene, D3DERR_INVALIDCALL);
1202 user_assert(!zs || !pSourceRect ||
1203 (pSourceRect->left == 0 &&
1204 pSourceRect->top == 0 &&
1205 pSourceRect->right == src->desc.Width &&
1206 pSourceRect->bottom == src->desc.Height), D3DERR_INVALIDCALL);
1207 user_assert(!zs || !pDestRect ||
1208 (pDestRect->left == 0 &&
1209 pDestRect->top == 0 &&
1210 pDestRect->right == dst->desc.Width &&
1211 pDestRect->bottom == dst->desc.Height), D3DERR_INVALIDCALL);
1212 user_assert(!zs ||
1213 (dst->desc.Width == src->desc.Width &&
1214 dst->desc.Height == src->desc.Height), D3DERR_INVALIDCALL);
1215 user_assert(zs || !util_format_is_depth_or_stencil(src_res->format),
1216 D3DERR_INVALIDCALL);
1217 user_assert(!zs || dst->desc.Format == src->desc.Format,
1218 D3DERR_INVALIDCALL);
1219 user_assert(screen->is_format_supported(screen, src_res->format,
1220 src_res->target,
1221 src_res->nr_samples,
1222 PIPE_BIND_SAMPLER_VIEW),
1223 D3DERR_INVALIDCALL);
1224 user_assert(dst->base.pool == D3DPOOL_DEFAULT &&
1225 src->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
1226
1227 /* We might want to permit these, but wine thinks we shouldn't. */
1228 user_assert(!pDestRect ||
1229 (pDestRect->left <= pDestRect->right &&
1230 pDestRect->top <= pDestRect->bottom), D3DERR_INVALIDCALL);
1231 user_assert(!pSourceRect ||
1232 (pSourceRect->left <= pSourceRect->right &&
1233 pSourceRect->top <= pSourceRect->bottom), D3DERR_INVALIDCALL);
1234
1235 blit.dst.resource = dst_res;
1236 blit.dst.level = dst->level;
1237 blit.dst.box.z = dst->layer;
1238 blit.dst.box.depth = 1;
1239 blit.dst.format = dst_res->format;
1240 if (pDestRect) {
1241 flip_x = pDestRect->left > pDestRect->right;
1242 if (flip_x) {
1243 blit.dst.box.x = pDestRect->right;
1244 blit.dst.box.width = pDestRect->left - pDestRect->right;
1245 } else {
1246 blit.dst.box.x = pDestRect->left;
1247 blit.dst.box.width = pDestRect->right - pDestRect->left;
1248 }
1249 flip_y = pDestRect->top > pDestRect->bottom;
1250 if (flip_y) {
1251 blit.dst.box.y = pDestRect->bottom;
1252 blit.dst.box.height = pDestRect->top - pDestRect->bottom;
1253 } else {
1254 blit.dst.box.y = pDestRect->top;
1255 blit.dst.box.height = pDestRect->bottom - pDestRect->top;
1256 }
1257 } else {
1258 blit.dst.box.x = 0;
1259 blit.dst.box.y = 0;
1260 blit.dst.box.width = dst->desc.Width;
1261 blit.dst.box.height = dst->desc.Height;
1262 }
1263 blit.src.resource = src_res;
1264 blit.src.level = src->level;
1265 blit.src.box.z = src->layer;
1266 blit.src.box.depth = 1;
1267 blit.src.format = src_res->format;
1268 if (pSourceRect) {
1269 if (flip_x ^ (pSourceRect->left > pSourceRect->right)) {
1270 blit.src.box.x = pSourceRect->right;
1271 blit.src.box.width = pSourceRect->left - pSourceRect->right;
1272 } else {
1273 blit.src.box.x = pSourceRect->left;
1274 blit.src.box.width = pSourceRect->right - pSourceRect->left;
1275 }
1276 if (flip_y ^ (pSourceRect->top > pSourceRect->bottom)) {
1277 blit.src.box.y = pSourceRect->bottom;
1278 blit.src.box.height = pSourceRect->top - pSourceRect->bottom;
1279 } else {
1280 blit.src.box.y = pSourceRect->top;
1281 blit.src.box.height = pSourceRect->bottom - pSourceRect->top;
1282 }
1283 } else {
1284 blit.src.box.x = flip_x ? src->desc.Width : 0;
1285 blit.src.box.y = flip_y ? src->desc.Height : 0;
1286 blit.src.box.width = flip_x ? -src->desc.Width : src->desc.Width;
1287 blit.src.box.height = flip_y ? -src->desc.Height : src->desc.Height;
1288 }
1289 blit.mask = zs ? PIPE_MASK_ZS : PIPE_MASK_RGBA;
1290 blit.filter = Filter == D3DTEXF_LINEAR ?
1291 PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST;
1292 blit.scissor_enable = FALSE;
1293
1294 /* If both of a src and dst dimension are negative, flip them. */
1295 if (blit.dst.box.width < 0 && blit.src.box.width < 0) {
1296 blit.dst.box.width = -blit.dst.box.width;
1297 blit.src.box.width = -blit.src.box.width;
1298 }
1299 if (blit.dst.box.height < 0 && blit.src.box.height < 0) {
1300 blit.dst.box.height = -blit.dst.box.height;
1301 blit.src.box.height = -blit.src.box.height;
1302 }
1303 scaled =
1304 blit.dst.box.width != blit.src.box.width ||
1305 blit.dst.box.height != blit.src.box.height;
1306
1307 user_assert(!scaled || dst != src, D3DERR_INVALIDCALL);
1308 user_assert(!scaled ||
1309 !NineSurface9_IsOffscreenPlain(dst) ||
1310 NineSurface9_IsOffscreenPlain(src), D3DERR_INVALIDCALL);
1311 user_assert(!scaled ||
1312 (!util_format_is_compressed(dst->base.info.format) &&
1313 !util_format_is_compressed(src->base.info.format)),
1314 D3DERR_INVALIDCALL);
1315
1316 user_warn(src == dst &&
1317 u_box_test_intersection_2d(&blit.src.box, &blit.dst.box));
1318
1319 /* Check for clipping/clamping: */
1320 {
1321 struct pipe_box box;
1322 int xy;
1323
1324 xy = u_box_clip_2d(&box, &blit.dst.box,
1325 dst->desc.Width, dst->desc.Height);
1326 if (xy < 0)
1327 return D3D_OK;
1328 if (xy == 0)
1329 xy = u_box_clip_2d(&box, &blit.src.box,
1330 src->desc.Width, src->desc.Height);
1331 clamped = !!xy;
1332 }
1333
1334 ms = (dst->desc.MultiSampleType | 1) != (src->desc.MultiSampleType | 1);
1335
1336 if (clamped || scaled || (blit.dst.format != blit.src.format) || ms) {
1337 DBG("using pipe->blit()\n");
1338 /* TODO: software scaling */
1339 user_assert(screen->is_format_supported(screen, dst_res->format,
1340 dst_res->target,
1341 dst_res->nr_samples,
1342 zs ? PIPE_BIND_DEPTH_STENCIL :
1343 PIPE_BIND_RENDER_TARGET),
1344 D3DERR_INVALIDCALL);
1345
1346 pipe->blit(pipe, &blit);
1347 } else {
1348 assert(blit.dst.box.x >= 0 && blit.dst.box.y >= 0 &&
1349 blit.src.box.x >= 0 && blit.src.box.y >= 0 &&
1350 blit.dst.box.x + blit.dst.box.width <= dst->desc.Width &&
1351 blit.src.box.x + blit.src.box.width <= src->desc.Width &&
1352 blit.dst.box.y + blit.dst.box.height <= dst->desc.Height &&
1353 blit.src.box.y + blit.src.box.height <= src->desc.Height);
1354 /* Or drivers might crash ... */
1355 DBG("Using resource_copy_region.\n");
1356 pipe->resource_copy_region(pipe,
1357 blit.dst.resource, blit.dst.level,
1358 blit.dst.box.x, blit.dst.box.y, blit.dst.box.z,
1359 blit.src.resource, blit.src.level,
1360 &blit.src.box);
1361 }
1362
1363 return D3D_OK;
1364 }
1365
1366 HRESULT WINAPI
1367 NineDevice9_ColorFill( struct NineDevice9 *This,
1368 IDirect3DSurface9 *pSurface,
1369 const RECT *pRect,
1370 D3DCOLOR color )
1371 {
1372 struct pipe_context *pipe = This->pipe;
1373 struct NineSurface9 *surf = NineSurface9(pSurface);
1374 struct pipe_surface *psurf;
1375 unsigned x, y, w, h;
1376 union pipe_color_union rgba;
1377 boolean fallback;
1378
1379 DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This,
1380 pSurface, pRect, color);
1381 if (pRect)
1382 DBG("pRect=(%u,%u)-(%u,%u)\n", pRect->left, pRect->top,
1383 pRect->right, pRect->bottom);
1384
1385 user_assert(surf->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
1386
1387 user_assert((surf->base.usage & D3DUSAGE_RENDERTARGET) ||
1388 NineSurface9_IsOffscreenPlain(surf), D3DERR_INVALIDCALL);
1389
1390 if (pRect) {
1391 x = pRect->left;
1392 y = pRect->top;
1393 w = pRect->right - pRect->left;
1394 h = pRect->bottom - pRect->top;
1395 } else{
1396 x = 0;
1397 y = 0;
1398 w = surf->desc.Width;
1399 h = surf->desc.Height;
1400 }
1401 d3dcolor_to_pipe_color_union(&rgba, color);
1402
1403 fallback =
1404 !This->screen->is_format_supported(This->screen, surf->base.info.format,
1405 surf->base.info.target,
1406 surf->base.info.nr_samples,
1407 PIPE_BIND_RENDER_TARGET);
1408 if (!fallback) {
1409 psurf = NineSurface9_GetSurface(surf, 0);
1410 if (!psurf)
1411 fallback = TRUE;
1412 }
1413
1414 if (!fallback) {
1415 pipe->clear_render_target(pipe, psurf, &rgba, x, y, w, h);
1416 } else {
1417 D3DLOCKED_RECT lock;
1418 union util_color uc;
1419 HRESULT hr;
1420 /* XXX: lock pRect and fix util_fill_rect */
1421 hr = NineSurface9_LockRect(surf, &lock, NULL, 0);
1422 if (FAILED(hr))
1423 return hr;
1424 util_pack_color_ub(color >> 16, color >> 8, color >> 0, color >> 24,
1425 surf->base.info.format, &uc);
1426 util_fill_rect(lock.pBits, surf->base.info.format,lock.Pitch,
1427 x, y, w, h, &uc);
1428 NineSurface9_UnlockRect(surf);
1429 }
1430
1431 return D3D_OK;
1432 }
1433
1434 HRESULT WINAPI
1435 NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This,
1436 UINT Width,
1437 UINT Height,
1438 D3DFORMAT Format,
1439 D3DPOOL Pool,
1440 IDirect3DSurface9 **ppSurface,
1441 HANDLE *pSharedHandle )
1442 {
1443 HRESULT hr;
1444
1445 DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u "
1446 "ppSurface=%p pSharedHandle=%p\n", This,
1447 Width, Height, d3dformat_to_string(Format), Format, Pool,
1448 ppSurface, pSharedHandle);
1449
1450 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT
1451 || Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
1452 user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL);
1453
1454 /* Can be used with StretchRect and ColorFill. It's also always lockable.
1455 */
1456 hr = create_zs_or_rt_surface(This, 2, Pool, Width, Height,
1457 Format,
1458 D3DMULTISAMPLE_NONE, 0,
1459 TRUE,
1460 ppSurface, pSharedHandle);
1461 if (FAILED(hr))
1462 DBG("Failed to create surface.\n");
1463 return hr;
1464 }
1465
1466 HRESULT WINAPI
1467 NineDevice9_SetRenderTarget( struct NineDevice9 *This,
1468 DWORD RenderTargetIndex,
1469 IDirect3DSurface9 *pRenderTarget )
1470 {
1471 struct NineSurface9 *rt = NineSurface9(pRenderTarget);
1472 const unsigned i = RenderTargetIndex;
1473
1474 DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This,
1475 RenderTargetIndex, pRenderTarget);
1476
1477 user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL);
1478 user_assert(i != 0 || pRenderTarget, D3DERR_INVALIDCALL);
1479 user_assert(!pRenderTarget ||
1480 rt->desc.Usage & D3DUSAGE_RENDERTARGET, D3DERR_INVALIDCALL);
1481
1482 if (i == 0) {
1483 This->state.viewport.X = 0;
1484 This->state.viewport.Y = 0;
1485 This->state.viewport.Width = rt->desc.Width;
1486 This->state.viewport.Height = rt->desc.Height;
1487 This->state.viewport.MinZ = 0.0f;
1488 This->state.viewport.MaxZ = 1.0f;
1489
1490 This->state.scissor.minx = 0;
1491 This->state.scissor.miny = 0;
1492 This->state.scissor.maxx = rt->desc.Width;
1493 This->state.scissor.maxy = rt->desc.Height;
1494
1495 This->state.changed.group |= NINE_STATE_VIEWPORT | NINE_STATE_SCISSOR;
1496 }
1497
1498 if (This->state.rt[i] != NineSurface9(pRenderTarget)) {
1499 nine_bind(&This->state.rt[i], pRenderTarget);
1500 This->state.changed.group |= NINE_STATE_FB;
1501 }
1502 return D3D_OK;
1503 }
1504
1505 HRESULT WINAPI
1506 NineDevice9_GetRenderTarget( struct NineDevice9 *This,
1507 DWORD RenderTargetIndex,
1508 IDirect3DSurface9 **ppRenderTarget )
1509 {
1510 const unsigned i = RenderTargetIndex;
1511
1512 user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL);
1513 user_assert(ppRenderTarget, D3DERR_INVALIDCALL);
1514
1515 *ppRenderTarget = (IDirect3DSurface9 *)This->state.rt[i];
1516 if (!This->state.rt[i])
1517 return D3DERR_NOTFOUND;
1518
1519 NineUnknown_AddRef(NineUnknown(This->state.rt[i]));
1520 return D3D_OK;
1521 }
1522
1523 HRESULT WINAPI
1524 NineDevice9_SetDepthStencilSurface( struct NineDevice9 *This,
1525 IDirect3DSurface9 *pNewZStencil )
1526 {
1527 DBG("This=%p pNewZStencil=%p\n", This, pNewZStencil);
1528
1529 if (This->state.ds != NineSurface9(pNewZStencil)) {
1530 nine_bind(&This->state.ds, pNewZStencil);
1531 This->state.changed.group |= NINE_STATE_FB;
1532 }
1533 return D3D_OK;
1534 }
1535
1536 HRESULT WINAPI
1537 NineDevice9_GetDepthStencilSurface( struct NineDevice9 *This,
1538 IDirect3DSurface9 **ppZStencilSurface )
1539 {
1540 user_assert(ppZStencilSurface, D3DERR_INVALIDCALL);
1541
1542 *ppZStencilSurface = (IDirect3DSurface9 *)This->state.ds;
1543 if (!This->state.ds)
1544 return D3DERR_NOTFOUND;
1545
1546 NineUnknown_AddRef(NineUnknown(This->state.ds));
1547 return D3D_OK;
1548 }
1549
1550 HRESULT WINAPI
1551 NineDevice9_BeginScene( struct NineDevice9 *This )
1552 {
1553 DBG("This=%p\n", This);
1554 user_assert(!This->in_scene, D3DERR_INVALIDCALL);
1555 This->in_scene = TRUE;
1556 /* Do we want to do anything else here ? */
1557 return D3D_OK;
1558 }
1559
1560 HRESULT WINAPI
1561 NineDevice9_EndScene( struct NineDevice9 *This )
1562 {
1563 DBG("This=%p\n", This);
1564 user_assert(This->in_scene, D3DERR_INVALIDCALL);
1565 This->in_scene = FALSE;
1566 return D3D_OK;
1567 }
1568
1569 HRESULT WINAPI
1570 NineDevice9_Clear( struct NineDevice9 *This,
1571 DWORD Count,
1572 const D3DRECT *pRects,
1573 DWORD Flags,
1574 D3DCOLOR Color,
1575 float Z,
1576 DWORD Stencil )
1577 {
1578 struct pipe_context *pipe = This->pipe;
1579 struct NineSurface9 *zsbuf = This->state.ds;
1580 unsigned bufs = 0;
1581 unsigned r, i;
1582 union pipe_color_union rgba;
1583 D3DRECT rect;
1584
1585 DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n",
1586 This, Count, pRects, Flags, Color, Z, Stencil);
1587
1588 user_assert(This->state.ds || !(Flags & NINED3DCLEAR_DEPTHSTENCIL),
1589 D3DERR_INVALIDCALL);
1590 user_assert(!(Flags & D3DCLEAR_STENCIL) ||
1591 (zsbuf &&
1592 util_format_is_depth_and_stencil(zsbuf->base.info.format)),
1593 D3DERR_INVALIDCALL);
1594 #ifdef NINE_STRICT
1595 user_assert((Count && pRects) || (!Count && !pRects), D3DERR_INVALIDCALL);
1596 #else
1597 user_warn((pRects && !Count) || (!pRects && Count));
1598 if (pRects && !Count)
1599 return D3D_OK;
1600 if (!pRects)
1601 Count = 0;
1602 #endif
1603
1604 if (Flags & D3DCLEAR_TARGET) bufs |= PIPE_CLEAR_COLOR;
1605 if (Flags & D3DCLEAR_ZBUFFER) bufs |= PIPE_CLEAR_DEPTH;
1606 if (Flags & D3DCLEAR_STENCIL) bufs |= PIPE_CLEAR_STENCIL;
1607 if (!bufs)
1608 return D3D_OK;
1609 d3dcolor_to_pipe_color_union(&rgba, Color);
1610
1611 nine_update_state(This, NINE_STATE_FB);
1612
1613 rect.x1 = This->state.viewport.X;
1614 rect.y1 = This->state.viewport.Y;
1615 rect.x2 = This->state.viewport.Width + rect.x1;
1616 rect.y2 = This->state.viewport.Height + rect.y1;
1617
1618 /* Both rectangles apply, which is weird, but that's D3D9. */
1619 if (This->state.rs[D3DRS_SCISSORTESTENABLE]) {
1620 rect.x1 = MAX2(rect.x1, This->state.scissor.minx);
1621 rect.y1 = MAX2(rect.y1, This->state.scissor.miny);
1622 rect.x2 = MIN2(rect.x2, This->state.scissor.maxx);
1623 rect.y2 = MIN2(rect.y2, This->state.scissor.maxy);
1624 }
1625
1626 if (Count) {
1627 /* Maybe apps like to specify a large rect ? */
1628 if (pRects[0].x1 <= rect.x1 && pRects[0].x2 >= rect.x2 &&
1629 pRects[0].y1 <= rect.y1 && pRects[0].y2 >= rect.y2) {
1630 DBG("First rect covers viewport.\n");
1631 Count = 0;
1632 pRects = NULL;
1633 }
1634 }
1635
1636 if (rect.x1 >= This->state.fb.width || rect.y1 >= This->state.fb.height)
1637 return D3D_OK;
1638 if (!Count &&
1639 rect.x1 == 0 && rect.x2 >= This->state.fb.width &&
1640 rect.y1 == 0 && rect.y2 >= This->state.fb.height) {
1641 /* fast path, clears everything at once */
1642 DBG("fast path\n");
1643 pipe->clear(pipe, bufs, &rgba, Z, Stencil);
1644 return D3D_OK;
1645 }
1646 rect.x2 = MIN2(rect.x2, This->state.fb.width);
1647 rect.y2 = MIN2(rect.y2, This->state.fb.height);
1648
1649 if (!Count) {
1650 Count = 1;
1651 pRects = &rect;
1652 }
1653
1654 for (i = 0; (i < This->state.fb.nr_cbufs); ++i) {
1655 if (!This->state.fb.cbufs[i] || !(Flags & D3DCLEAR_TARGET))
1656 continue; /* save space, compiler should hoist this */
1657 for (r = 0; r < Count; ++r) {
1658 /* Don't trust users to pass these in the right order. */
1659 unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2);
1660 unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2);
1661 unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2);
1662 unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2);
1663 #ifndef NINE_LAX
1664 /* Drop negative rectangles (like wine expects). */
1665 if (pRects[r].x1 > pRects[r].x2) continue;
1666 if (pRects[r].y1 > pRects[r].y2) continue;
1667 #endif
1668
1669 x1 = MAX2(x1, rect.x1);
1670 y1 = MAX2(y1, rect.y1);
1671 x2 = MIN2(x2, rect.x2);
1672 y2 = MIN2(y2, rect.y2);
1673
1674 DBG("Clearing (%u..%u)x(%u..%u)\n", x1, x2, y1, y2);
1675 pipe->clear_render_target(pipe, This->state.fb.cbufs[i], &rgba,
1676 x1, y1, x2 - x1, y2 - y1);
1677 }
1678 }
1679 if (!(Flags & NINED3DCLEAR_DEPTHSTENCIL))
1680 return D3D_OK;
1681
1682 bufs &= PIPE_CLEAR_DEPTHSTENCIL;
1683
1684 for (r = 0; r < Count; ++r) {
1685 unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2);
1686 unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2);
1687 unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2);
1688 unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2);
1689 #ifndef NINE_LAX
1690 /* Drop negative rectangles. */
1691 if (pRects[r].x1 > pRects[r].x2) continue;
1692 if (pRects[r].y1 > pRects[r].y2) continue;
1693 #endif
1694
1695 x1 = MIN2(x1, rect.x1);
1696 y1 = MIN2(y1, rect.y1);
1697 x2 = MIN2(x2, rect.x2);
1698 y2 = MIN2(y2, rect.y2);
1699
1700 pipe->clear_depth_stencil(pipe, This->state.fb.zsbuf, bufs, Z, Stencil,
1701 x1, y1, x2 - x1, y2 - y1);
1702 }
1703 return D3D_OK;
1704 }
1705
1706 HRESULT WINAPI
1707 NineDevice9_SetTransform( struct NineDevice9 *This,
1708 D3DTRANSFORMSTATETYPE State,
1709 const D3DMATRIX *pMatrix )
1710 {
1711 struct nine_state *state = This->update;
1712 D3DMATRIX *M = nine_state_access_transform(state, State, TRUE);
1713 user_assert(M, D3DERR_INVALIDCALL);
1714
1715 *M = *pMatrix;
1716 state->ff.changed.transform[State / 32] |= 1 << (State % 32);
1717 state->changed.group |= NINE_STATE_FF;
1718
1719 return D3D_OK;
1720 }
1721
1722 HRESULT WINAPI
1723 NineDevice9_GetTransform( struct NineDevice9 *This,
1724 D3DTRANSFORMSTATETYPE State,
1725 D3DMATRIX *pMatrix )
1726 {
1727 D3DMATRIX *M = nine_state_access_transform(&This->state, State, FALSE);
1728 user_assert(M, D3DERR_INVALIDCALL);
1729 *pMatrix = *M;
1730 return D3D_OK;
1731 }
1732
1733 HRESULT WINAPI
1734 NineDevice9_MultiplyTransform( struct NineDevice9 *This,
1735 D3DTRANSFORMSTATETYPE State,
1736 const D3DMATRIX *pMatrix )
1737 {
1738 struct nine_state *state = This->update;
1739 D3DMATRIX T;
1740 D3DMATRIX *M = nine_state_access_transform(state, State, TRUE);
1741 user_assert(M, D3DERR_INVALIDCALL);
1742
1743 nine_d3d_matrix_matrix_mul(&T, pMatrix, M);
1744 return NineDevice9_SetTransform(This, State, &T);
1745 }
1746
1747 HRESULT WINAPI
1748 NineDevice9_SetViewport( struct NineDevice9 *This,
1749 const D3DVIEWPORT9 *pViewport )
1750 {
1751 struct nine_state *state = This->update;
1752
1753 DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n",
1754 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height,
1755 pViewport->MinZ, pViewport->MaxZ);
1756
1757 state->viewport = *pViewport;
1758 state->changed.group |= NINE_STATE_VIEWPORT;
1759
1760 return D3D_OK;
1761 }
1762
1763 HRESULT WINAPI
1764 NineDevice9_GetViewport( struct NineDevice9 *This,
1765 D3DVIEWPORT9 *pViewport )
1766 {
1767 *pViewport = This->state.viewport;
1768 return D3D_OK;
1769 }
1770
1771 HRESULT WINAPI
1772 NineDevice9_SetMaterial( struct NineDevice9 *This,
1773 const D3DMATERIAL9 *pMaterial )
1774 {
1775 struct nine_state *state = This->update;
1776
1777 DBG("This=%p pMaterial=%p\n", This, pMaterial);
1778 if (pMaterial)
1779 nine_dump_D3DMATERIAL9(DBG_FF, pMaterial);
1780
1781 user_assert(pMaterial, E_POINTER);
1782
1783 state->ff.material = *pMaterial;
1784 state->changed.group |= NINE_STATE_FF_MATERIAL;
1785
1786 return D3D_OK;
1787 }
1788
1789 HRESULT WINAPI
1790 NineDevice9_GetMaterial( struct NineDevice9 *This,
1791 D3DMATERIAL9 *pMaterial )
1792 {
1793 user_assert(pMaterial, E_POINTER);
1794 *pMaterial = This->state.ff.material;
1795 return D3D_OK;
1796 }
1797
1798 HRESULT WINAPI
1799 NineDevice9_SetLight( struct NineDevice9 *This,
1800 DWORD Index,
1801 const D3DLIGHT9 *pLight )
1802 {
1803 struct nine_state *state = This->update;
1804
1805 DBG("This=%p Index=%u pLight=%p\n", This, Index, pLight);
1806 if (pLight)
1807 nine_dump_D3DLIGHT9(DBG_FF, pLight);
1808
1809 user_assert(pLight, D3DERR_INVALIDCALL);
1810 user_assert(pLight->Type < NINED3DLIGHT_INVALID, D3DERR_INVALIDCALL);
1811
1812 user_assert(Index < NINE_MAX_LIGHTS, D3DERR_INVALIDCALL); /* sanity */
1813
1814 if (Index >= state->ff.num_lights) {
1815 unsigned n = state->ff.num_lights;
1816 unsigned N = Index + 1;
1817
1818 state->ff.light = REALLOC(state->ff.light, n * sizeof(D3DLIGHT9),
1819 N * sizeof(D3DLIGHT9));
1820 if (!state->ff.light)
1821 return E_OUTOFMEMORY;
1822 state->ff.num_lights = N;
1823
1824 for (; n < Index; ++n)
1825 state->ff.light[n].Type = (D3DLIGHTTYPE)NINED3DLIGHT_INVALID;
1826 }
1827 state->ff.light[Index] = *pLight;
1828
1829 if (pLight->Type == D3DLIGHT_SPOT && pLight->Theta >= pLight->Phi) {
1830 DBG("Warning: clamping D3DLIGHT9.Theta\n");
1831 state->ff.light[Index].Theta = state->ff.light[Index].Phi;
1832 }
1833 if (pLight->Type != D3DLIGHT_DIRECTIONAL &&
1834 pLight->Attenuation0 == 0.0f &&
1835 pLight->Attenuation1 == 0.0f &&
1836 pLight->Attenuation2 == 0.0f) {
1837 DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n");
1838 }
1839
1840 state->changed.group |= NINE_STATE_FF_LIGHTING;
1841
1842 return D3D_OK;
1843 }
1844
1845 HRESULT WINAPI
1846 NineDevice9_GetLight( struct NineDevice9 *This,
1847 DWORD Index,
1848 D3DLIGHT9 *pLight )
1849 {
1850 const struct nine_state *state = &This->state;
1851
1852 user_assert(pLight, D3DERR_INVALIDCALL);
1853 user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL);
1854 user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID,
1855 D3DERR_INVALIDCALL);
1856
1857 *pLight = state->ff.light[Index];
1858
1859 return D3D_OK;
1860 }
1861
1862 HRESULT WINAPI
1863 NineDevice9_LightEnable( struct NineDevice9 *This,
1864 DWORD Index,
1865 BOOL Enable )
1866 {
1867 struct nine_state *state = This->update;
1868 unsigned i;
1869
1870 DBG("This=%p Index=%u Enable=%i\n", This, Index, Enable);
1871
1872 if (Index >= state->ff.num_lights ||
1873 state->ff.light[Index].Type == NINED3DLIGHT_INVALID) {
1874 /* This should create a default light. */
1875 D3DLIGHT9 light;
1876 memset(&light, 0, sizeof(light));
1877 light.Type = D3DLIGHT_DIRECTIONAL;
1878 light.Diffuse.r = 1.0f;
1879 light.Diffuse.g = 1.0f;
1880 light.Diffuse.b = 1.0f;
1881 light.Direction.z = 1.0f;
1882 NineDevice9_SetLight(This, Index, &light);
1883 }
1884 user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL);
1885
1886 for (i = 0; i < state->ff.num_lights_active; ++i) {
1887 if (state->ff.active_light[i] == Index)
1888 break;
1889 }
1890
1891 if (Enable) {
1892 if (i < state->ff.num_lights_active)
1893 return D3D_OK;
1894 /* XXX wine thinks this should still succeed:
1895 */
1896 user_assert(i < NINE_MAX_LIGHTS_ACTIVE, D3DERR_INVALIDCALL);
1897
1898 state->ff.active_light[i] = Index;
1899 state->ff.num_lights_active++;
1900 } else {
1901 if (i == state->ff.num_lights_active)
1902 return D3D_OK;
1903 --state->ff.num_lights_active;
1904 for (; i < state->ff.num_lights_active; ++i)
1905 state->ff.active_light[i] = state->ff.active_light[i + 1];
1906 }
1907 state->changed.group |= NINE_STATE_FF_LIGHTING;
1908
1909 return D3D_OK;
1910 }
1911
1912 HRESULT WINAPI
1913 NineDevice9_GetLightEnable( struct NineDevice9 *This,
1914 DWORD Index,
1915 BOOL *pEnable )
1916 {
1917 const struct nine_state *state = &This->state;
1918 unsigned i;
1919
1920 user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL);
1921 user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID,
1922 D3DERR_INVALIDCALL);
1923
1924 for (i = 0; i < state->ff.num_lights_active; ++i)
1925 if (state->ff.active_light[i] == Index)
1926 break;
1927 *pEnable = i != state->ff.num_lights_active;
1928 return D3D_OK;
1929 }
1930
1931 HRESULT WINAPI
1932 NineDevice9_SetClipPlane( struct NineDevice9 *This,
1933 DWORD Index,
1934 const float *pPlane )
1935 {
1936 struct nine_state *state = This->update;
1937
1938 DBG("This=%p Index=%u pPlane=%p(%f %f %f %f)\n", This, Index, pPlane,
1939 pPlane ? pPlane[0] : 0.0f, pPlane ? pPlane[1] : 0.0f,
1940 pPlane ? pPlane[2] : 0.0f, pPlane ? pPlane[3] : 0.0f);
1941
1942 user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL);
1943
1944 memcpy(&state->clip.ucp[Index][0], pPlane, sizeof(state->clip.ucp[0]));
1945 state->changed.ucp |= 1 << Index;
1946
1947 return D3D_OK;
1948 }
1949
1950 HRESULT WINAPI
1951 NineDevice9_GetClipPlane( struct NineDevice9 *This,
1952 DWORD Index,
1953 float *pPlane )
1954 {
1955 const struct nine_state *state = &This->state;
1956
1957 user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL);
1958
1959 memcpy(pPlane, &state->clip.ucp[Index][0], sizeof(state->clip.ucp[0]));
1960 return D3D_OK;
1961 }
1962
1963 HRESULT WINAPI
1964 NineDevice9_SetRenderState( struct NineDevice9 *This,
1965 D3DRENDERSTATETYPE State,
1966 DWORD Value )
1967 {
1968 struct nine_state *state = This->update;
1969
1970 DBG("This=%p State=%u(%s) Value=%08x\n", This,
1971 State, nine_d3drs_to_string(State), Value);
1972
1973 user_assert(State < Elements(state->rs), D3DERR_INVALIDCALL);
1974
1975 if (likely(state->rs[State] != Value) || unlikely(This->is_recording)) {
1976 state->rs[State] = Value;
1977 state->changed.rs[State / 32] |= 1 << (State % 32);
1978 state->changed.group |= nine_render_state_group[State];
1979 }
1980
1981 return D3D_OK;
1982 }
1983
1984 HRESULT WINAPI
1985 NineDevice9_GetRenderState( struct NineDevice9 *This,
1986 D3DRENDERSTATETYPE State,
1987 DWORD *pValue )
1988 {
1989 user_assert(State < Elements(This->state.rs), D3DERR_INVALIDCALL);
1990
1991 *pValue = This->state.rs[State];
1992 return D3D_OK;
1993 }
1994
1995 HRESULT WINAPI
1996 NineDevice9_CreateStateBlock( struct NineDevice9 *This,
1997 D3DSTATEBLOCKTYPE Type,
1998 IDirect3DStateBlock9 **ppSB )
1999 {
2000 struct NineStateBlock9 *nsb;
2001 struct nine_state *dst;
2002 HRESULT hr;
2003 enum nine_stateblock_type type;
2004 unsigned s;
2005
2006 DBG("This=%p Type=%u ppSB=%p\n", This, Type, ppSB);
2007
2008 user_assert(Type == D3DSBT_ALL ||
2009 Type == D3DSBT_VERTEXSTATE ||
2010 Type == D3DSBT_PIXELSTATE, D3DERR_INVALIDCALL);
2011
2012 switch (Type) {
2013 case D3DSBT_VERTEXSTATE: type = NINESBT_VERTEXSTATE; break;
2014 case D3DSBT_PIXELSTATE: type = NINESBT_PIXELSTATE; break;
2015 default:
2016 type = NINESBT_ALL;
2017 break;
2018 }
2019
2020 hr = NineStateBlock9_new(This, &nsb, type);
2021 if (FAILED(hr))
2022 return hr;
2023 *ppSB = (IDirect3DStateBlock9 *)nsb;
2024 dst = &nsb->state;
2025
2026 dst->changed.group =
2027 NINE_STATE_TEXTURE |
2028 NINE_STATE_SAMPLER;
2029
2030 if (Type == D3DSBT_ALL || Type == D3DSBT_VERTEXSTATE) {
2031 dst->changed.group |=
2032 NINE_STATE_FF_LIGHTING |
2033 NINE_STATE_VS | NINE_STATE_VS_CONST |
2034 NINE_STATE_VDECL;
2035 /* TODO: texture/sampler state */
2036 memcpy(dst->changed.rs,
2037 nine_render_states_vertex, sizeof(dst->changed.rs));
2038 nine_ranges_insert(&dst->changed.vs_const_f, 0, This->max_vs_const_f,
2039 &This->range_pool);
2040 dst->changed.vs_const_i = 0xffff;
2041 dst->changed.vs_const_b = 0xffff;
2042 for (s = 0; s < NINE_MAX_SAMPLERS; ++s)
2043 dst->changed.sampler[s] |= 1 << D3DSAMP_DMAPOFFSET;
2044 if (This->state.ff.num_lights) {
2045 dst->ff.num_lights = This->state.ff.num_lights;
2046 /* zero'd -> light type won't be NINED3DLIGHT_INVALID, so
2047 * all currently existing lights will be captured
2048 */
2049 dst->ff.light = CALLOC(This->state.ff.num_lights,
2050 sizeof(D3DLIGHT9));
2051 if (!dst->ff.light) {
2052 nine_bind(ppSB, NULL);
2053 return E_OUTOFMEMORY;
2054 }
2055 }
2056 }
2057 if (Type == D3DSBT_ALL || Type == D3DSBT_PIXELSTATE) {
2058 dst->changed.group |=
2059 NINE_STATE_PS | NINE_STATE_PS_CONST;
2060 /* TODO: texture/sampler state */
2061 memcpy(dst->changed.rs,
2062 nine_render_states_pixel, sizeof(dst->changed.rs));
2063 nine_ranges_insert(&dst->changed.ps_const_f, 0, This->max_ps_const_f,
2064 &This->range_pool);
2065 dst->changed.ps_const_i = 0xffff;
2066 dst->changed.ps_const_b = 0xffff;
2067 for (s = 0; s < NINE_MAX_SAMPLERS; ++s)
2068 dst->changed.sampler[s] |= 0x1ffe;
2069 }
2070 if (Type == D3DSBT_ALL) {
2071 dst->changed.group |=
2072 NINE_STATE_VIEWPORT |
2073 NINE_STATE_SCISSOR |
2074 NINE_STATE_RASTERIZER |
2075 NINE_STATE_BLEND |
2076 NINE_STATE_DSA |
2077 NINE_STATE_IDXBUF |
2078 NINE_STATE_MATERIAL |
2079 NINE_STATE_BLEND_COLOR |
2080 NINE_STATE_SAMPLE_MASK;
2081 memset(dst->changed.rs, ~0, (D3DRS_COUNT / 32) * sizeof(uint32_t));
2082 dst->changed.rs[D3DRS_LAST / 32] |= (1 << (D3DRS_COUNT % 32)) - 1;
2083 dst->changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1;
2084 dst->changed.stream_freq = dst->changed.vtxbuf;
2085 dst->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
2086 dst->changed.texture = (1 << NINE_MAX_SAMPLERS) - 1;
2087 }
2088 NineStateBlock9_Capture(NineStateBlock9(*ppSB));
2089
2090 /* TODO: fixed function state */
2091
2092 return D3D_OK;
2093 }
2094
2095 HRESULT WINAPI
2096 NineDevice9_BeginStateBlock( struct NineDevice9 *This )
2097 {
2098 HRESULT hr;
2099
2100 DBG("This=%p\n", This);
2101
2102 user_assert(!This->record, D3DERR_INVALIDCALL);
2103
2104 hr = NineStateBlock9_new(This, &This->record, NINESBT_CUSTOM);
2105 if (FAILED(hr))
2106 return hr;
2107 NineUnknown_ConvertRefToBind(NineUnknown(This->record));
2108
2109 This->update = &This->record->state;
2110 This->is_recording = TRUE;
2111
2112 return D3D_OK;
2113 }
2114
2115 HRESULT WINAPI
2116 NineDevice9_EndStateBlock( struct NineDevice9 *This,
2117 IDirect3DStateBlock9 **ppSB )
2118 {
2119 DBG("This=%p ppSB=%p\n", This, ppSB);
2120
2121 user_assert(This->record, D3DERR_INVALIDCALL);
2122
2123 This->update = &This->state;
2124 This->is_recording = FALSE;
2125
2126 NineUnknown_AddRef(NineUnknown(This->record));
2127 *ppSB = (IDirect3DStateBlock9 *)This->record;
2128 NineUnknown_Unbind(NineUnknown(This->record));
2129 This->record = NULL;
2130
2131 return D3D_OK;
2132 }
2133
2134 HRESULT WINAPI
2135 NineDevice9_SetClipStatus( struct NineDevice9 *This,
2136 const D3DCLIPSTATUS9 *pClipStatus )
2137 {
2138 STUB(D3DERR_INVALIDCALL);
2139 }
2140
2141 HRESULT WINAPI
2142 NineDevice9_GetClipStatus( struct NineDevice9 *This,
2143 D3DCLIPSTATUS9 *pClipStatus )
2144 {
2145 STUB(D3DERR_INVALIDCALL);
2146 }
2147
2148 HRESULT WINAPI
2149 NineDevice9_GetTexture( struct NineDevice9 *This,
2150 DWORD Stage,
2151 IDirect3DBaseTexture9 **ppTexture )
2152 {
2153 user_assert(Stage < This->caps.MaxSimultaneousTextures ||
2154 Stage == D3DDMAPSAMPLER ||
2155 (Stage >= D3DVERTEXTEXTURESAMPLER0 &&
2156 Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
2157 user_assert(ppTexture, D3DERR_INVALIDCALL);
2158
2159 if (Stage >= D3DDMAPSAMPLER)
2160 Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
2161
2162 *ppTexture = (IDirect3DBaseTexture9 *)This->state.texture[Stage];
2163
2164 if (This->state.texture[Stage])
2165 NineUnknown_AddRef(NineUnknown(This->state.texture[Stage]));
2166 return D3D_OK;
2167 }
2168
2169 HRESULT WINAPI
2170 NineDevice9_SetTexture( struct NineDevice9 *This,
2171 DWORD Stage,
2172 IDirect3DBaseTexture9 *pTexture )
2173 {
2174 struct nine_state *state = This->update;
2175
2176 DBG("This=%p Stage=%u pTexture=%p\n", This, Stage, pTexture);
2177
2178 user_assert(Stage < This->caps.MaxSimultaneousTextures ||
2179 Stage == D3DDMAPSAMPLER ||
2180 (Stage >= D3DVERTEXTEXTURESAMPLER0 &&
2181 Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
2182
2183 if (Stage >= D3DDMAPSAMPLER)
2184 Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
2185
2186 if (!This->is_recording) {
2187 struct NineBaseTexture9 *tex = NineBaseTexture9(pTexture);
2188 struct NineBaseTexture9 *old = state->texture[Stage];
2189 if (old == tex)
2190 return D3D_OK;
2191
2192 state->samplers_shadow &= ~(1 << Stage);
2193 if (tex) {
2194 state->samplers_shadow |= tex->shadow << Stage;
2195
2196 if ((tex->dirty | tex->dirty_mip) && LIST_IS_EMPTY(&tex->list))
2197 list_add(&tex->list, &This->update_textures);
2198
2199 tex->bind_count++;
2200 }
2201 if (old)
2202 old->bind_count--;
2203 }
2204 nine_bind(&state->texture[Stage], pTexture);
2205
2206 state->changed.texture |= 1 << Stage;
2207 state->changed.group |= NINE_STATE_TEXTURE;
2208
2209 return D3D_OK;
2210 }
2211
2212 HRESULT WINAPI
2213 NineDevice9_GetTextureStageState( struct NineDevice9 *This,
2214 DWORD Stage,
2215 D3DTEXTURESTAGESTATETYPE Type,
2216 DWORD *pValue )
2217 {
2218 const struct nine_state *state = &This->state;
2219
2220 user_assert(Stage < Elements(state->ff.tex_stage), D3DERR_INVALIDCALL);
2221 user_assert(Type < Elements(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);
2222
2223 *pValue = state->ff.tex_stage[Stage][Type];
2224
2225 return D3D_OK;
2226 }
2227
2228 HRESULT WINAPI
2229 NineDevice9_SetTextureStageState( struct NineDevice9 *This,
2230 DWORD Stage,
2231 D3DTEXTURESTAGESTATETYPE Type,
2232 DWORD Value )
2233 {
2234 struct nine_state *state = This->update;
2235
2236 DBG("Stage=%u Type=%u Value=%08x\n", Stage, Type, Value);
2237 nine_dump_D3DTSS_value(DBG_FF, Type, Value);
2238
2239 user_assert(Stage < Elements(state->ff.tex_stage), D3DERR_INVALIDCALL);
2240 user_assert(Type < Elements(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);
2241
2242 state->ff.tex_stage[Stage][Type] = Value;
2243
2244 state->changed.group |= NINE_STATE_FF_PSSTAGES;
2245 state->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32);
2246
2247 return D3D_OK;
2248 }
2249
2250 HRESULT WINAPI
2251 NineDevice9_GetSamplerState( struct NineDevice9 *This,
2252 DWORD Sampler,
2253 D3DSAMPLERSTATETYPE Type,
2254 DWORD *pValue )
2255 {
2256 user_assert(Sampler < This->caps.MaxSimultaneousTextures ||
2257 Sampler == D3DDMAPSAMPLER ||
2258 (Sampler >= D3DVERTEXTEXTURESAMPLER0 &&
2259 Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
2260
2261 if (Sampler >= D3DDMAPSAMPLER)
2262 Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
2263
2264 *pValue = This->state.samp[Sampler][Type];
2265 return D3D_OK;
2266 }
2267
2268 HRESULT WINAPI
2269 NineDevice9_SetSamplerState( struct NineDevice9 *This,
2270 DWORD Sampler,
2271 D3DSAMPLERSTATETYPE Type,
2272 DWORD Value )
2273 {
2274 struct nine_state *state = This->update;
2275
2276 DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This,
2277 Sampler, nine_D3DSAMP_to_str(Type), Value);
2278
2279 user_assert(Sampler < This->caps.MaxSimultaneousTextures ||
2280 Sampler == D3DDMAPSAMPLER ||
2281 (Sampler >= D3DVERTEXTEXTURESAMPLER0 &&
2282 Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
2283
2284 if (Sampler >= D3DDMAPSAMPLER)
2285 Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
2286
2287 state->samp[Sampler][Type] = Value;
2288 state->changed.group |= NINE_STATE_SAMPLER;
2289 state->changed.sampler[Sampler] |= 1 << Type;
2290
2291 return D3D_OK;
2292 }
2293
2294 HRESULT WINAPI
2295 NineDevice9_ValidateDevice( struct NineDevice9 *This,
2296 DWORD *pNumPasses )
2297 {
2298 const struct nine_state *state = &This->state;
2299 unsigned i;
2300 unsigned w = 0, h = 0;
2301
2302 DBG("This=%p pNumPasses=%p\n", This, pNumPasses);
2303
2304 for (i = 0; i < Elements(state->samp); ++i) {
2305 if (state->samp[i][D3DSAMP_MINFILTER] == D3DTEXF_NONE ||
2306 state->samp[i][D3DSAMP_MAGFILTER] == D3DTEXF_NONE)
2307 return D3DERR_UNSUPPORTEDTEXTUREFILTER;
2308 }
2309
2310 for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) {
2311 if (!state->rt[i])
2312 continue;
2313 if (w == 0) {
2314 w = state->rt[i]->desc.Width;
2315 h = state->rt[i]->desc.Height;
2316 } else
2317 if (state->rt[i]->desc.Width != w || state->rt[i]->desc.Height != h) {
2318 return D3DERR_CONFLICTINGRENDERSTATE;
2319 }
2320 }
2321 if (state->ds &&
2322 (state->rs[D3DRS_ZENABLE] || state->rs[D3DRS_STENCILENABLE])) {
2323 if (w != 0 &&
2324 (state->ds->desc.Width != w || state->ds->desc.Height != h))
2325 return D3DERR_CONFLICTINGRENDERSTATE;
2326 }
2327
2328 if (pNumPasses)
2329 *pNumPasses = 1;
2330
2331 return D3D_OK;
2332 }
2333
2334 HRESULT WINAPI
2335 NineDevice9_SetPaletteEntries( struct NineDevice9 *This,
2336 UINT PaletteNumber,
2337 const PALETTEENTRY *pEntries )
2338 {
2339 STUB(D3D_OK); /* like wine */
2340 }
2341
2342 HRESULT WINAPI
2343 NineDevice9_GetPaletteEntries( struct NineDevice9 *This,
2344 UINT PaletteNumber,
2345 PALETTEENTRY *pEntries )
2346 {
2347 STUB(D3DERR_INVALIDCALL);
2348 }
2349
2350 HRESULT WINAPI
2351 NineDevice9_SetCurrentTexturePalette( struct NineDevice9 *This,
2352 UINT PaletteNumber )
2353 {
2354 STUB(D3D_OK); /* like wine */
2355 }
2356
2357 HRESULT WINAPI
2358 NineDevice9_GetCurrentTexturePalette( struct NineDevice9 *This,
2359 UINT *PaletteNumber )
2360 {
2361 STUB(D3DERR_INVALIDCALL);
2362 }
2363
2364 HRESULT WINAPI
2365 NineDevice9_SetScissorRect( struct NineDevice9 *This,
2366 const RECT *pRect )
2367 {
2368 struct nine_state *state = This->update;
2369
2370 DBG("x=(%u..%u) y=(%u..%u)\n",
2371 pRect->left, pRect->top, pRect->right, pRect->bottom);
2372
2373 state->scissor.minx = pRect->left;
2374 state->scissor.miny = pRect->top;
2375 state->scissor.maxx = pRect->right;
2376 state->scissor.maxy = pRect->bottom;
2377
2378 state->changed.group |= NINE_STATE_SCISSOR;
2379
2380 return D3D_OK;
2381 }
2382
2383 HRESULT WINAPI
2384 NineDevice9_GetScissorRect( struct NineDevice9 *This,
2385 RECT *pRect )
2386 {
2387 pRect->left = This->state.scissor.minx;
2388 pRect->top = This->state.scissor.miny;
2389 pRect->right = This->state.scissor.maxx;
2390 pRect->bottom = This->state.scissor.maxy;
2391
2392 return D3D_OK;
2393 }
2394
2395 HRESULT WINAPI
2396 NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This,
2397 BOOL bSoftware )
2398 {
2399 STUB(D3DERR_INVALIDCALL);
2400 }
2401
2402 BOOL WINAPI
2403 NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This )
2404 {
2405 return !!(This->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING);
2406 }
2407
2408 HRESULT WINAPI
2409 NineDevice9_SetNPatchMode( struct NineDevice9 *This,
2410 float nSegments )
2411 {
2412 STUB(D3DERR_INVALIDCALL);
2413 }
2414
2415 float WINAPI
2416 NineDevice9_GetNPatchMode( struct NineDevice9 *This )
2417 {
2418 STUB(0);
2419 }
2420
2421 static INLINE void
2422 init_draw_info(struct pipe_draw_info *info,
2423 struct NineDevice9 *dev, D3DPRIMITIVETYPE type, UINT count)
2424 {
2425 info->mode = d3dprimitivetype_to_pipe_prim(type);
2426 info->count = prim_count_to_vertex_count(type, count);
2427 info->start_instance = 0;
2428 info->instance_count = 1;
2429 if (dev->state.stream_instancedata_mask & dev->state.stream_usage_mask)
2430 info->instance_count = MAX2(dev->state.stream_freq[0] & 0x7FFFFF, 1);
2431 info->primitive_restart = FALSE;
2432 info->restart_index = 0;
2433 info->count_from_stream_output = NULL;
2434 info->indirect = NULL;
2435 }
2436
2437 HRESULT WINAPI
2438 NineDevice9_DrawPrimitive( struct NineDevice9 *This,
2439 D3DPRIMITIVETYPE PrimitiveType,
2440 UINT StartVertex,
2441 UINT PrimitiveCount )
2442 {
2443 struct pipe_draw_info info;
2444
2445 DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n",
2446 This, PrimitiveType, StartVertex, PrimitiveCount);
2447
2448 nine_update_state(This, ~0);
2449
2450 init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
2451 info.indexed = FALSE;
2452 info.start = StartVertex;
2453 info.index_bias = 0;
2454 info.min_index = info.start;
2455 info.max_index = info.count - 1;
2456
2457 This->pipe->draw_vbo(This->pipe, &info);
2458
2459 return D3D_OK;
2460 }
2461
2462 HRESULT WINAPI
2463 NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This,
2464 D3DPRIMITIVETYPE PrimitiveType,
2465 INT BaseVertexIndex,
2466 UINT MinVertexIndex,
2467 UINT NumVertices,
2468 UINT StartIndex,
2469 UINT PrimitiveCount )
2470 {
2471 struct pipe_draw_info info;
2472
2473 DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u "
2474 "NumVertices %u, StartIndex %u, PrimitiveCount %u\n",
2475 This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices,
2476 StartIndex, PrimitiveCount);
2477
2478 user_assert(This->state.idxbuf, D3DERR_INVALIDCALL);
2479 user_assert(This->state.vdecl, D3DERR_INVALIDCALL);
2480
2481 nine_update_state(This, ~0);
2482
2483 init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
2484 info.indexed = TRUE;
2485 info.start = StartIndex;
2486 info.index_bias = BaseVertexIndex;
2487 /* These don't include index bias: */
2488 info.min_index = MinVertexIndex;
2489 info.max_index = MinVertexIndex + NumVertices - 1;
2490
2491 This->pipe->draw_vbo(This->pipe, &info);
2492
2493 return D3D_OK;
2494 }
2495
2496 HRESULT WINAPI
2497 NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This,
2498 D3DPRIMITIVETYPE PrimitiveType,
2499 UINT PrimitiveCount,
2500 const void *pVertexStreamZeroData,
2501 UINT VertexStreamZeroStride )
2502 {
2503 struct pipe_vertex_buffer vtxbuf;
2504 struct pipe_draw_info info;
2505
2506 DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n",
2507 This, PrimitiveType, PrimitiveCount,
2508 pVertexStreamZeroData, VertexStreamZeroStride);
2509
2510 user_assert(pVertexStreamZeroData && VertexStreamZeroStride,
2511 D3DERR_INVALIDCALL);
2512
2513 nine_update_state(This, ~0);
2514
2515 init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
2516 info.indexed = FALSE;
2517 info.start = 0;
2518 info.index_bias = 0;
2519 info.min_index = 0;
2520 info.max_index = info.count - 1;
2521
2522 vtxbuf.stride = VertexStreamZeroStride;
2523 vtxbuf.buffer_offset = 0;
2524 vtxbuf.buffer = NULL;
2525 vtxbuf.user_buffer = pVertexStreamZeroData;
2526
2527 if (!This->driver_caps.user_vbufs)
2528 u_upload_data(This->upload,
2529 0,
2530 (info.max_index + 1) * VertexStreamZeroStride, /* XXX */
2531 vtxbuf.user_buffer,
2532 &vtxbuf.buffer_offset,
2533 &vtxbuf.buffer);
2534
2535 This->pipe->set_vertex_buffers(This->pipe, 0, 1, &vtxbuf);
2536
2537 This->pipe->draw_vbo(This->pipe, &info);
2538
2539 NineDevice9_PauseRecording(This);
2540 NineDevice9_SetStreamSource(This, 0, NULL, 0, 0);
2541 NineDevice9_ResumeRecording(This);
2542
2543 pipe_resource_reference(&vtxbuf.buffer, NULL);
2544
2545 return D3D_OK;
2546 }
2547
2548 HRESULT WINAPI
2549 NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,
2550 D3DPRIMITIVETYPE PrimitiveType,
2551 UINT MinVertexIndex,
2552 UINT NumVertices,
2553 UINT PrimitiveCount,
2554 const void *pIndexData,
2555 D3DFORMAT IndexDataFormat,
2556 const void *pVertexStreamZeroData,
2557 UINT VertexStreamZeroStride )
2558 {
2559 struct pipe_draw_info info;
2560 struct pipe_vertex_buffer vbuf;
2561 struct pipe_index_buffer ibuf;
2562
2563 DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u "
2564 "PrimitiveCount %u, pIndexData %p, IndexDataFormat %u "
2565 "pVertexStreamZeroData %p, VertexStreamZeroStride %u\n",
2566 This, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount,
2567 pIndexData, IndexDataFormat,
2568 pVertexStreamZeroData, VertexStreamZeroStride);
2569
2570 user_assert(pIndexData && pVertexStreamZeroData, D3DERR_INVALIDCALL);
2571 user_assert(VertexStreamZeroStride, D3DERR_INVALIDCALL);
2572 user_assert(IndexDataFormat == D3DFMT_INDEX16 ||
2573 IndexDataFormat == D3DFMT_INDEX32, D3DERR_INVALIDCALL);
2574
2575 nine_update_state(This, ~0);
2576
2577 init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
2578 info.indexed = TRUE;
2579 info.start = 0;
2580 info.index_bias = 0;
2581 info.min_index = MinVertexIndex;
2582 info.max_index = MinVertexIndex + NumVertices - 1;
2583
2584 vbuf.stride = VertexStreamZeroStride;
2585 vbuf.buffer_offset = 0;
2586 vbuf.buffer = NULL;
2587 vbuf.user_buffer = pVertexStreamZeroData;
2588
2589 ibuf.index_size = (IndexDataFormat == D3DFMT_INDEX16) ? 2 : 4;
2590 ibuf.offset = 0;
2591 ibuf.buffer = NULL;
2592 ibuf.user_buffer = pIndexData;
2593
2594 if (!This->driver_caps.user_vbufs) {
2595 const unsigned base = info.min_index * VertexStreamZeroStride;
2596 u_upload_data(This->upload,
2597 base,
2598 (info.max_index -
2599 info.min_index + 1) * VertexStreamZeroStride, /* XXX */
2600 (const uint8_t *)vbuf.user_buffer + base,
2601 &vbuf.buffer_offset,
2602 &vbuf.buffer);
2603 /* Won't be used: */
2604 vbuf.buffer_offset -= base;
2605 }
2606 if (!This->driver_caps.user_ibufs)
2607 u_upload_data(This->upload,
2608 0,
2609 info.count * ibuf.index_size,
2610 ibuf.user_buffer,
2611 &ibuf.offset,
2612 &ibuf.buffer);
2613
2614 This->pipe->set_vertex_buffers(This->pipe, 0, 1, &vbuf);
2615 This->pipe->set_index_buffer(This->pipe, &ibuf);
2616
2617 This->pipe->draw_vbo(This->pipe, &info);
2618
2619 pipe_resource_reference(&vbuf.buffer, NULL);
2620 pipe_resource_reference(&ibuf.buffer, NULL);
2621
2622 NineDevice9_PauseRecording(This);
2623 NineDevice9_SetIndices(This, NULL);
2624 NineDevice9_SetStreamSource(This, 0, NULL, 0, 0);
2625 NineDevice9_ResumeRecording(This);
2626
2627 return D3D_OK;
2628 }
2629
2630 /* TODO: Write to pDestBuffer directly if vertex declaration contains
2631 * only f32 formats.
2632 */
2633 HRESULT WINAPI
2634 NineDevice9_ProcessVertices( struct NineDevice9 *This,
2635 UINT SrcStartIndex,
2636 UINT DestIndex,
2637 UINT VertexCount,
2638 IDirect3DVertexBuffer9 *pDestBuffer,
2639 IDirect3DVertexDeclaration9 *pVertexDecl,
2640 DWORD Flags )
2641 {
2642 struct pipe_screen *screen = This->screen;
2643 struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pVertexDecl);
2644 struct NineVertexShader9 *vs;
2645 struct pipe_resource *resource;
2646 struct pipe_stream_output_target *target;
2647 struct pipe_draw_info draw;
2648 HRESULT hr;
2649 unsigned buffer_offset, buffer_size;
2650
2651 if (!screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS))
2652 STUB(D3DERR_INVALIDCALL);
2653
2654 nine_update_state(This, ~0);
2655
2656 /* TODO: Create shader with stream output. */
2657 STUB(D3DERR_INVALIDCALL);
2658 struct NineVertexBuffer9 *dst = NineVertexBuffer9(pDestBuffer);
2659
2660 vs = This->state.vs ? This->state.vs : This->ff.vs;
2661
2662 buffer_size = VertexCount * vs->so->stride[0];
2663 if (1) {
2664 struct pipe_resource templ;
2665
2666 templ.target = PIPE_BUFFER;
2667 templ.format = PIPE_FORMAT_R8_UNORM;
2668 templ.width0 = buffer_size;
2669 templ.flags = 0;
2670 templ.bind = PIPE_BIND_STREAM_OUTPUT;
2671 templ.usage = PIPE_USAGE_STREAM;
2672 templ.height0 = templ.depth0 = templ.array_size = 1;
2673 templ.last_level = templ.nr_samples = 0;
2674
2675 resource = This->screen->resource_create(This->screen, &templ);
2676 if (!resource)
2677 return E_OUTOFMEMORY;
2678 buffer_offset = 0;
2679 } else {
2680 /* SO matches vertex declaration */
2681 resource = dst->base.resource;
2682 buffer_offset = DestIndex * vs->so->stride[0];
2683 }
2684 target = This->pipe->create_stream_output_target(This->pipe, resource,
2685 buffer_offset,
2686 buffer_size);
2687 if (!target) {
2688 pipe_resource_reference(&resource, NULL);
2689 return D3DERR_DRIVERINTERNALERROR;
2690 }
2691
2692 if (!vdecl) {
2693 hr = NineVertexDeclaration9_new_from_fvf(This, dst->desc.FVF, &vdecl);
2694 if (FAILED(hr))
2695 goto out;
2696 }
2697
2698 init_draw_info(&draw, This, D3DPT_POINTLIST, VertexCount);
2699 draw.instance_count = 1;
2700 draw.indexed = FALSE;
2701 draw.start = SrcStartIndex;
2702 draw.index_bias = 0;
2703 draw.min_index = SrcStartIndex;
2704 draw.max_index = SrcStartIndex + VertexCount - 1;
2705
2706 This->pipe->set_stream_output_targets(This->pipe, 1, &target, 0);
2707 This->pipe->draw_vbo(This->pipe, &draw);
2708 This->pipe->set_stream_output_targets(This->pipe, 0, NULL, 0);
2709 This->pipe->stream_output_target_destroy(This->pipe, target);
2710
2711 hr = NineVertexDeclaration9_ConvertStreamOutput(vdecl,
2712 dst, DestIndex, VertexCount,
2713 resource, vs->so);
2714 out:
2715 pipe_resource_reference(&resource, NULL);
2716 if (!pVertexDecl)
2717 NineUnknown_Release(NineUnknown(vdecl));
2718 return hr;
2719 }
2720
2721 HRESULT WINAPI
2722 NineDevice9_CreateVertexDeclaration( struct NineDevice9 *This,
2723 const D3DVERTEXELEMENT9 *pVertexElements,
2724 IDirect3DVertexDeclaration9 **ppDecl )
2725 {
2726 struct NineVertexDeclaration9 *vdecl;
2727
2728 HRESULT hr = NineVertexDeclaration9_new(This, pVertexElements, &vdecl);
2729 if (SUCCEEDED(hr))
2730 *ppDecl = (IDirect3DVertexDeclaration9 *)vdecl;
2731
2732 return hr;
2733 }
2734
2735 HRESULT WINAPI
2736 NineDevice9_SetVertexDeclaration( struct NineDevice9 *This,
2737 IDirect3DVertexDeclaration9 *pDecl )
2738 {
2739 struct nine_state *state = This->update;
2740
2741 DBG("This=%p pDecl=%p\n", This, pDecl);
2742
2743 if (likely(!This->is_recording) && state->vdecl == NineVertexDeclaration9(pDecl))
2744 return D3D_OK;
2745 nine_bind(&state->vdecl, pDecl);
2746
2747 state->changed.group |= NINE_STATE_VDECL;
2748
2749 return D3D_OK;
2750 }
2751
2752 HRESULT WINAPI
2753 NineDevice9_GetVertexDeclaration( struct NineDevice9 *This,
2754 IDirect3DVertexDeclaration9 **ppDecl )
2755 {
2756 user_assert(ppDecl, D3DERR_INVALIDCALL);
2757
2758 *ppDecl = (IDirect3DVertexDeclaration9 *)This->state.vdecl;
2759 if (*ppDecl)
2760 NineUnknown_AddRef(NineUnknown(*ppDecl));
2761 return D3D_OK;
2762 }
2763
2764 HRESULT WINAPI
2765 NineDevice9_SetFVF( struct NineDevice9 *This,
2766 DWORD FVF )
2767 {
2768 struct NineVertexDeclaration9 *vdecl;
2769 HRESULT hr;
2770
2771 DBG("FVF = %08x\n", FVF);
2772 if (!FVF)
2773 return D3D_OK; /* like wine */
2774
2775 vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF);
2776 if (!vdecl) {
2777 hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl);
2778 if (FAILED(hr))
2779 return hr;
2780 vdecl->fvf = FVF;
2781 util_hash_table_set(This->ff.ht_fvf, &vdecl->fvf, vdecl);
2782 NineUnknown_ConvertRefToBind(NineUnknown(vdecl));
2783 }
2784 return NineDevice9_SetVertexDeclaration(
2785 This, (IDirect3DVertexDeclaration9 *)vdecl);
2786 }
2787
2788 HRESULT WINAPI
2789 NineDevice9_GetFVF( struct NineDevice9 *This,
2790 DWORD *pFVF )
2791 {
2792 *pFVF = This->state.vdecl ? This->state.vdecl->fvf : 0;
2793 return D3D_OK;
2794 }
2795
2796 HRESULT WINAPI
2797 NineDevice9_CreateVertexShader( struct NineDevice9 *This,
2798 const DWORD *pFunction,
2799 IDirect3DVertexShader9 **ppShader )
2800 {
2801 struct NineVertexShader9 *vs;
2802 HRESULT hr;
2803
2804 hr = NineVertexShader9_new(This, &vs, pFunction, NULL);
2805 if (FAILED(hr))
2806 return hr;
2807 *ppShader = (IDirect3DVertexShader9 *)vs;
2808 return D3D_OK;
2809 }
2810
2811 HRESULT WINAPI
2812 NineDevice9_SetVertexShader( struct NineDevice9 *This,
2813 IDirect3DVertexShader9 *pShader )
2814 {
2815 struct nine_state *state = This->update;
2816
2817 DBG("This=%p pShader=%p\n", This, pShader);
2818
2819 nine_bind(&state->vs, pShader);
2820
2821 state->changed.group |= NINE_STATE_VS;
2822
2823 return D3D_OK;
2824 }
2825
2826 HRESULT WINAPI
2827 NineDevice9_GetVertexShader( struct NineDevice9 *This,
2828 IDirect3DVertexShader9 **ppShader )
2829 {
2830 user_assert(ppShader, D3DERR_INVALIDCALL);
2831 nine_reference_set(ppShader, This->state.vs);
2832 return D3D_OK;
2833 }
2834
2835 HRESULT WINAPI
2836 NineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This,
2837 UINT StartRegister,
2838 const float *pConstantData,
2839 UINT Vector4fCount )
2840 {
2841 struct nine_state *state = This->update;
2842
2843 DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
2844 This, StartRegister, pConstantData, Vector4fCount);
2845
2846 user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
2847 user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
2848
2849 if (!Vector4fCount)
2850 return D3D_OK;
2851 user_assert(pConstantData, D3DERR_INVALIDCALL);
2852
2853 memcpy(&state->vs_const_f[StartRegister * 4],
2854 pConstantData,
2855 Vector4fCount * 4 * sizeof(state->vs_const_f[0]));
2856
2857 nine_ranges_insert(&state->changed.vs_const_f,
2858 StartRegister, StartRegister + Vector4fCount,
2859 &This->range_pool);
2860
2861 state->changed.group |= NINE_STATE_VS_CONST;
2862
2863 return D3D_OK;
2864 }
2865
2866 HRESULT WINAPI
2867 NineDevice9_GetVertexShaderConstantF( struct NineDevice9 *This,
2868 UINT StartRegister,
2869 float *pConstantData,
2870 UINT Vector4fCount )
2871 {
2872 const struct nine_state *state = &This->state;
2873
2874 user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
2875 user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
2876 user_assert(pConstantData, D3DERR_INVALIDCALL);
2877
2878 memcpy(pConstantData,
2879 &state->vs_const_f[StartRegister * 4],
2880 Vector4fCount * 4 * sizeof(state->vs_const_f[0]));
2881
2882 return D3D_OK;
2883 }
2884
2885 HRESULT WINAPI
2886 NineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This,
2887 UINT StartRegister,
2888 const int *pConstantData,
2889 UINT Vector4iCount )
2890 {
2891 struct nine_state *state = This->update;
2892
2893 DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
2894 This, StartRegister, pConstantData, Vector4iCount);
2895
2896 user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
2897 user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
2898 user_assert(pConstantData, D3DERR_INVALIDCALL);
2899
2900 memcpy(&state->vs_const_i[StartRegister][0],
2901 pConstantData,
2902 Vector4iCount * sizeof(state->vs_const_i[0]));
2903
2904 state->changed.vs_const_i |= ((1 << Vector4iCount) - 1) << StartRegister;
2905 state->changed.group |= NINE_STATE_VS_CONST;
2906
2907 return D3D_OK;
2908 }
2909
2910 HRESULT WINAPI
2911 NineDevice9_GetVertexShaderConstantI( struct NineDevice9 *This,
2912 UINT StartRegister,
2913 int *pConstantData,
2914 UINT Vector4iCount )
2915 {
2916 const struct nine_state *state = &This->state;
2917
2918 user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
2919 user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
2920 user_assert(pConstantData, D3DERR_INVALIDCALL);
2921
2922 memcpy(pConstantData,
2923 &state->vs_const_i[StartRegister][0],
2924 Vector4iCount * sizeof(state->vs_const_i[0]));
2925
2926 return D3D_OK;
2927 }
2928
2929 HRESULT WINAPI
2930 NineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This,
2931 UINT StartRegister,
2932 const BOOL *pConstantData,
2933 UINT BoolCount )
2934 {
2935 struct nine_state *state = This->update;
2936
2937 DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
2938 This, StartRegister, pConstantData, BoolCount);
2939
2940 user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
2941 user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
2942 user_assert(pConstantData, D3DERR_INVALIDCALL);
2943
2944 memcpy(&state->vs_const_b[StartRegister],
2945 pConstantData,
2946 BoolCount * sizeof(state->vs_const_b[0]));
2947
2948 state->changed.vs_const_b |= ((1 << BoolCount) - 1) << StartRegister;
2949 state->changed.group |= NINE_STATE_VS_CONST;
2950
2951 return D3D_OK;
2952 }
2953
2954 HRESULT WINAPI
2955 NineDevice9_GetVertexShaderConstantB( struct NineDevice9 *This,
2956 UINT StartRegister,
2957 BOOL *pConstantData,
2958 UINT BoolCount )
2959 {
2960 const struct nine_state *state = &This->state;
2961
2962 user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
2963 user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
2964 user_assert(pConstantData, D3DERR_INVALIDCALL);
2965
2966 memcpy(pConstantData,
2967 &state->vs_const_b[StartRegister],
2968 BoolCount * sizeof(state->vs_const_b[0]));
2969
2970 return D3D_OK;
2971 }
2972
2973 HRESULT WINAPI
2974 NineDevice9_SetStreamSource( struct NineDevice9 *This,
2975 UINT StreamNumber,
2976 IDirect3DVertexBuffer9 *pStreamData,
2977 UINT OffsetInBytes,
2978 UINT Stride )
2979 {
2980 struct nine_state *state = This->update;
2981 struct NineVertexBuffer9 *pVBuf9 = NineVertexBuffer9(pStreamData);
2982 const unsigned i = StreamNumber;
2983
2984 user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
2985 user_assert(Stride <= This->caps.MaxStreamStride, D3DERR_INVALIDCALL);
2986
2987 if (likely(!This->is_recording)) {
2988 if (state->stream[i] == NineVertexBuffer9(pStreamData) &&
2989 state->vtxbuf[i].stride == Stride &&
2990 state->vtxbuf[i].buffer_offset == OffsetInBytes)
2991 return D3D_OK;
2992 }
2993 nine_bind(&state->stream[i], pStreamData);
2994
2995 state->changed.vtxbuf |= 1 << StreamNumber;
2996
2997 if (pStreamData) {
2998 state->vtxbuf[i].stride = Stride;
2999 state->vtxbuf[i].buffer_offset = OffsetInBytes;
3000 }
3001 state->vtxbuf[i].buffer = pStreamData ? pVBuf9->base.resource : NULL;
3002
3003 return D3D_OK;
3004 }
3005
3006 HRESULT WINAPI
3007 NineDevice9_GetStreamSource( struct NineDevice9 *This,
3008 UINT StreamNumber,
3009 IDirect3DVertexBuffer9 **ppStreamData,
3010 UINT *pOffsetInBytes,
3011 UINT *pStride )
3012 {
3013 const struct nine_state *state = &This->state;
3014 const unsigned i = StreamNumber;
3015
3016 user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
3017 user_assert(ppStreamData, D3DERR_INVALIDCALL);
3018
3019 nine_reference_set(ppStreamData, state->stream[i]);
3020 *pStride = state->vtxbuf[i].stride;
3021 *pOffsetInBytes = state->vtxbuf[i].buffer_offset;
3022
3023 return D3D_OK;
3024 }
3025
3026 HRESULT WINAPI
3027 NineDevice9_SetStreamSourceFreq( struct NineDevice9 *This,
3028 UINT StreamNumber,
3029 UINT Setting )
3030 {
3031 struct nine_state *state = This->update;
3032 /* const UINT freq = Setting & 0x7FFFFF; */
3033
3034 DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This,
3035 StreamNumber, Setting);
3036
3037 user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
3038 user_assert(StreamNumber != 0 || !(Setting & D3DSTREAMSOURCE_INSTANCEDATA),
3039 D3DERR_INVALIDCALL);
3040 user_assert(!((Setting & D3DSTREAMSOURCE_INSTANCEDATA) &&
3041 (Setting & D3DSTREAMSOURCE_INDEXEDDATA)), D3DERR_INVALIDCALL);
3042 user_assert(Setting, D3DERR_INVALIDCALL);
3043
3044 state->stream_freq[StreamNumber] = Setting;
3045
3046 if (Setting & D3DSTREAMSOURCE_INSTANCEDATA)
3047 state->stream_instancedata_mask |= 1 << StreamNumber;
3048 else
3049 state->stream_instancedata_mask &= ~(1 << StreamNumber);
3050
3051 state->changed.stream_freq |= 1 << StreamNumber;
3052 return D3D_OK;
3053 }
3054
3055 HRESULT WINAPI
3056 NineDevice9_GetStreamSourceFreq( struct NineDevice9 *This,
3057 UINT StreamNumber,
3058 UINT *pSetting )
3059 {
3060 user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
3061 *pSetting = This->state.stream_freq[StreamNumber];
3062 return D3D_OK;
3063 }
3064
3065 HRESULT WINAPI
3066 NineDevice9_SetIndices( struct NineDevice9 *This,
3067 IDirect3DIndexBuffer9 *pIndexData )
3068 {
3069 struct nine_state *state = This->update;
3070
3071 if (likely(!This->is_recording))
3072 if (state->idxbuf == NineIndexBuffer9(pIndexData))
3073 return D3D_OK;
3074 nine_bind(&state->idxbuf, pIndexData);
3075
3076 state->changed.group |= NINE_STATE_IDXBUF;
3077
3078 return D3D_OK;
3079 }
3080
3081 /* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense
3082 * here because it's an argument passed to the Draw calls.
3083 */
3084 HRESULT WINAPI
3085 NineDevice9_GetIndices( struct NineDevice9 *This,
3086 IDirect3DIndexBuffer9 **ppIndexData /*,
3087 UINT *pBaseVertexIndex */ )
3088 {
3089 user_assert(ppIndexData, D3DERR_INVALIDCALL);
3090 nine_reference_set(ppIndexData, This->state.idxbuf);
3091 return D3D_OK;
3092 }
3093
3094 HRESULT WINAPI
3095 NineDevice9_CreatePixelShader( struct NineDevice9 *This,
3096 const DWORD *pFunction,
3097 IDirect3DPixelShader9 **ppShader )
3098 {
3099 struct NinePixelShader9 *ps;
3100 HRESULT hr;
3101
3102 hr = NinePixelShader9_new(This, &ps, pFunction, NULL);
3103 if (FAILED(hr))
3104 return hr;
3105 *ppShader = (IDirect3DPixelShader9 *)ps;
3106 return D3D_OK;
3107 }
3108
3109 HRESULT WINAPI
3110 NineDevice9_SetPixelShader( struct NineDevice9 *This,
3111 IDirect3DPixelShader9 *pShader )
3112 {
3113 struct nine_state *state = This->update;
3114
3115 DBG("This=%p pShader=%p\n", This, pShader);
3116
3117 nine_bind(&state->ps, pShader);
3118
3119 state->changed.group |= NINE_STATE_PS;
3120
3121 return D3D_OK;
3122 }
3123
3124 HRESULT WINAPI
3125 NineDevice9_GetPixelShader( struct NineDevice9 *This,
3126 IDirect3DPixelShader9 **ppShader )
3127 {
3128 user_assert(ppShader, D3DERR_INVALIDCALL);
3129 nine_reference_set(ppShader, This->state.ps);
3130 return D3D_OK;
3131 }
3132
3133 HRESULT WINAPI
3134 NineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This,
3135 UINT StartRegister,
3136 const float *pConstantData,
3137 UINT Vector4fCount )
3138 {
3139 struct nine_state *state = This->update;
3140
3141 DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
3142 This, StartRegister, pConstantData, Vector4fCount);
3143
3144 user_assert(StartRegister < NINE_MAX_CONST_F, D3DERR_INVALIDCALL);
3145 user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F, D3DERR_INVALIDCALL);
3146
3147 if (!Vector4fCount)
3148 return D3D_OK;
3149 user_assert(pConstantData, D3DERR_INVALIDCALL);
3150
3151 memcpy(&state->ps_const_f[StartRegister * 4],
3152 pConstantData,
3153 Vector4fCount * 4 * sizeof(state->ps_const_f[0]));
3154
3155 nine_ranges_insert(&state->changed.ps_const_f,
3156 StartRegister, StartRegister + Vector4fCount,
3157 &This->range_pool);
3158
3159 state->changed.group |= NINE_STATE_PS_CONST;
3160
3161 return D3D_OK;
3162 }
3163
3164 HRESULT WINAPI
3165 NineDevice9_GetPixelShaderConstantF( struct NineDevice9 *This,
3166 UINT StartRegister,
3167 float *pConstantData,
3168 UINT Vector4fCount )
3169 {
3170 const struct nine_state *state = &This->state;
3171
3172 user_assert(StartRegister < NINE_MAX_CONST_F, D3DERR_INVALIDCALL);
3173 user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F, D3DERR_INVALIDCALL);
3174 user_assert(pConstantData, D3DERR_INVALIDCALL);
3175
3176 memcpy(pConstantData,
3177 &state->ps_const_f[StartRegister * 4],
3178 Vector4fCount * 4 * sizeof(state->ps_const_f[0]));
3179
3180 return D3D_OK;
3181 }
3182
3183 HRESULT WINAPI
3184 NineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This,
3185 UINT StartRegister,
3186 const int *pConstantData,
3187 UINT Vector4iCount )
3188 {
3189 struct nine_state *state = This->update;
3190
3191 DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
3192 This, StartRegister, pConstantData, Vector4iCount);
3193
3194 user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
3195 user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
3196 user_assert(pConstantData, D3DERR_INVALIDCALL);
3197
3198 memcpy(&state->ps_const_i[StartRegister][0],
3199 pConstantData,
3200 Vector4iCount * sizeof(state->ps_const_i[0]));
3201
3202 state->changed.ps_const_i |= ((1 << Vector4iCount) - 1) << StartRegister;
3203 state->changed.group |= NINE_STATE_PS_CONST;
3204
3205 return D3D_OK;
3206 }
3207
3208 HRESULT WINAPI
3209 NineDevice9_GetPixelShaderConstantI( struct NineDevice9 *This,
3210 UINT StartRegister,
3211 int *pConstantData,
3212 UINT Vector4iCount )
3213 {
3214 const struct nine_state *state = &This->state;
3215
3216 user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
3217 user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
3218 user_assert(pConstantData, D3DERR_INVALIDCALL);
3219
3220 memcpy(pConstantData,
3221 &state->ps_const_i[StartRegister][0],
3222 Vector4iCount * sizeof(state->ps_const_i[0]));
3223
3224 return D3D_OK;
3225 }
3226
3227 HRESULT WINAPI
3228 NineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This,
3229 UINT StartRegister,
3230 const BOOL *pConstantData,
3231 UINT BoolCount )
3232 {
3233 struct nine_state *state = This->update;
3234
3235 DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
3236 This, StartRegister, pConstantData, BoolCount);
3237
3238 user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
3239 user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
3240 user_assert(pConstantData, D3DERR_INVALIDCALL);
3241
3242 memcpy(&state->ps_const_b[StartRegister],
3243 pConstantData,
3244 BoolCount * sizeof(state->ps_const_b[0]));
3245
3246 state->changed.ps_const_b |= ((1 << BoolCount) - 1) << StartRegister;
3247 state->changed.group |= NINE_STATE_PS_CONST;
3248
3249 return D3D_OK;
3250 }
3251
3252 HRESULT WINAPI
3253 NineDevice9_GetPixelShaderConstantB( struct NineDevice9 *This,
3254 UINT StartRegister,
3255 BOOL *pConstantData,
3256 UINT BoolCount )
3257 {
3258 const struct nine_state *state = &This->state;
3259
3260 user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
3261 user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
3262 user_assert(pConstantData, D3DERR_INVALIDCALL);
3263
3264 memcpy(pConstantData,
3265 &state->ps_const_b[StartRegister],
3266 BoolCount * sizeof(state->ps_const_b[0]));
3267
3268 return D3D_OK;
3269 }
3270
3271 HRESULT WINAPI
3272 NineDevice9_DrawRectPatch( struct NineDevice9 *This,
3273 UINT Handle,
3274 const float *pNumSegs,
3275 const D3DRECTPATCH_INFO *pRectPatchInfo )
3276 {
3277 STUB(D3DERR_INVALIDCALL);
3278 }
3279
3280 HRESULT WINAPI
3281 NineDevice9_DrawTriPatch( struct NineDevice9 *This,
3282 UINT Handle,
3283 const float *pNumSegs,
3284 const D3DTRIPATCH_INFO *pTriPatchInfo )
3285 {
3286 STUB(D3DERR_INVALIDCALL);
3287 }
3288
3289 HRESULT WINAPI
3290 NineDevice9_DeletePatch( struct NineDevice9 *This,
3291 UINT Handle )
3292 {
3293 STUB(D3DERR_INVALIDCALL);
3294 }
3295
3296 HRESULT WINAPI
3297 NineDevice9_CreateQuery( struct NineDevice9 *This,
3298 D3DQUERYTYPE Type,
3299 IDirect3DQuery9 **ppQuery )
3300 {
3301 struct NineQuery9 *query;
3302 HRESULT hr;
3303
3304 if (!ppQuery)
3305 return nine_is_query_supported(Type);
3306
3307 hr = NineQuery9_new(This, &query, Type);
3308 if (FAILED(hr))
3309 return hr;
3310 *ppQuery = (IDirect3DQuery9 *)query;
3311 return D3D_OK;
3312 }
3313
3314 IDirect3DDevice9Vtbl NineDevice9_vtable = {
3315 (void *)NineUnknown_QueryInterface,
3316 (void *)NineUnknown_AddRef,
3317 (void *)NineUnknown_Release,
3318 (void *)NineDevice9_TestCooperativeLevel,
3319 (void *)NineDevice9_GetAvailableTextureMem,
3320 (void *)NineDevice9_EvictManagedResources,
3321 (void *)NineDevice9_GetDirect3D,
3322 (void *)NineDevice9_GetDeviceCaps,
3323 (void *)NineDevice9_GetDisplayMode,
3324 (void *)NineDevice9_GetCreationParameters,
3325 (void *)NineDevice9_SetCursorProperties,
3326 (void *)NineDevice9_SetCursorPosition,
3327 (void *)NineDevice9_ShowCursor,
3328 (void *)NineDevice9_CreateAdditionalSwapChain,
3329 (void *)NineDevice9_GetSwapChain,
3330 (void *)NineDevice9_GetNumberOfSwapChains,
3331 (void *)NineDevice9_Reset,
3332 (void *)NineDevice9_Present,
3333 (void *)NineDevice9_GetBackBuffer,
3334 (void *)NineDevice9_GetRasterStatus,
3335 (void *)NineDevice9_SetDialogBoxMode,
3336 (void *)NineDevice9_SetGammaRamp,
3337 (void *)NineDevice9_GetGammaRamp,
3338 (void *)NineDevice9_CreateTexture,
3339 (void *)NineDevice9_CreateVolumeTexture,
3340 (void *)NineDevice9_CreateCubeTexture,
3341 (void *)NineDevice9_CreateVertexBuffer,
3342 (void *)NineDevice9_CreateIndexBuffer,
3343 (void *)NineDevice9_CreateRenderTarget,
3344 (void *)NineDevice9_CreateDepthStencilSurface,
3345 (void *)NineDevice9_UpdateSurface,
3346 (void *)NineDevice9_UpdateTexture,
3347 (void *)NineDevice9_GetRenderTargetData,
3348 (void *)NineDevice9_GetFrontBufferData,
3349 (void *)NineDevice9_StretchRect,
3350 (void *)NineDevice9_ColorFill,
3351 (void *)NineDevice9_CreateOffscreenPlainSurface,
3352 (void *)NineDevice9_SetRenderTarget,
3353 (void *)NineDevice9_GetRenderTarget,
3354 (void *)NineDevice9_SetDepthStencilSurface,
3355 (void *)NineDevice9_GetDepthStencilSurface,
3356 (void *)NineDevice9_BeginScene,
3357 (void *)NineDevice9_EndScene,
3358 (void *)NineDevice9_Clear,
3359 (void *)NineDevice9_SetTransform,
3360 (void *)NineDevice9_GetTransform,
3361 (void *)NineDevice9_MultiplyTransform,
3362 (void *)NineDevice9_SetViewport,
3363 (void *)NineDevice9_GetViewport,
3364 (void *)NineDevice9_SetMaterial,
3365 (void *)NineDevice9_GetMaterial,
3366 (void *)NineDevice9_SetLight,
3367 (void *)NineDevice9_GetLight,
3368 (void *)NineDevice9_LightEnable,
3369 (void *)NineDevice9_GetLightEnable,
3370 (void *)NineDevice9_SetClipPlane,
3371 (void *)NineDevice9_GetClipPlane,
3372 (void *)NineDevice9_SetRenderState,
3373 (void *)NineDevice9_GetRenderState,
3374 (void *)NineDevice9_CreateStateBlock,
3375 (void *)NineDevice9_BeginStateBlock,
3376 (void *)NineDevice9_EndStateBlock,
3377 (void *)NineDevice9_SetClipStatus,
3378 (void *)NineDevice9_GetClipStatus,
3379 (void *)NineDevice9_GetTexture,
3380 (void *)NineDevice9_SetTexture,
3381 (void *)NineDevice9_GetTextureStageState,
3382 (void *)NineDevice9_SetTextureStageState,
3383 (void *)NineDevice9_GetSamplerState,
3384 (void *)NineDevice9_SetSamplerState,
3385 (void *)NineDevice9_ValidateDevice,
3386 (void *)NineDevice9_SetPaletteEntries,
3387 (void *)NineDevice9_GetPaletteEntries,
3388 (void *)NineDevice9_SetCurrentTexturePalette,
3389 (void *)NineDevice9_GetCurrentTexturePalette,
3390 (void *)NineDevice9_SetScissorRect,
3391 (void *)NineDevice9_GetScissorRect,
3392 (void *)NineDevice9_SetSoftwareVertexProcessing,
3393 (void *)NineDevice9_GetSoftwareVertexProcessing,
3394 (void *)NineDevice9_SetNPatchMode,
3395 (void *)NineDevice9_GetNPatchMode,
3396 (void *)NineDevice9_DrawPrimitive,
3397 (void *)NineDevice9_DrawIndexedPrimitive,
3398 (void *)NineDevice9_DrawPrimitiveUP,
3399 (void *)NineDevice9_DrawIndexedPrimitiveUP,
3400 (void *)NineDevice9_ProcessVertices,
3401 (void *)NineDevice9_CreateVertexDeclaration,
3402 (void *)NineDevice9_SetVertexDeclaration,
3403 (void *)NineDevice9_GetVertexDeclaration,
3404 (void *)NineDevice9_SetFVF,
3405 (void *)NineDevice9_GetFVF,
3406 (void *)NineDevice9_CreateVertexShader,
3407 (void *)NineDevice9_SetVertexShader,
3408 (void *)NineDevice9_GetVertexShader,
3409 (void *)NineDevice9_SetVertexShaderConstantF,
3410 (void *)NineDevice9_GetVertexShaderConstantF,
3411 (void *)NineDevice9_SetVertexShaderConstantI,
3412 (void *)NineDevice9_GetVertexShaderConstantI,
3413 (void *)NineDevice9_SetVertexShaderConstantB,
3414 (void *)NineDevice9_GetVertexShaderConstantB,
3415 (void *)NineDevice9_SetStreamSource,
3416 (void *)NineDevice9_GetStreamSource,
3417 (void *)NineDevice9_SetStreamSourceFreq,
3418 (void *)NineDevice9_GetStreamSourceFreq,
3419 (void *)NineDevice9_SetIndices,
3420 (void *)NineDevice9_GetIndices,
3421 (void *)NineDevice9_CreatePixelShader,
3422 (void *)NineDevice9_SetPixelShader,
3423 (void *)NineDevice9_GetPixelShader,
3424 (void *)NineDevice9_SetPixelShaderConstantF,
3425 (void *)NineDevice9_GetPixelShaderConstantF,
3426 (void *)NineDevice9_SetPixelShaderConstantI,
3427 (void *)NineDevice9_GetPixelShaderConstantI,
3428 (void *)NineDevice9_SetPixelShaderConstantB,
3429 (void *)NineDevice9_GetPixelShaderConstantB,
3430 (void *)NineDevice9_DrawRectPatch,
3431 (void *)NineDevice9_DrawTriPatch,
3432 (void *)NineDevice9_DeletePatch,
3433 (void *)NineDevice9_CreateQuery
3434 };
3435
3436 static const GUID *NineDevice9_IIDs[] = {
3437 &IID_IDirect3DDevice9,
3438 &IID_IUnknown,
3439 NULL
3440 };
3441
3442 HRESULT
3443 NineDevice9_new( struct pipe_screen *pScreen,
3444 D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
3445 D3DCAPS9 *pCaps,
3446 D3DPRESENT_PARAMETERS *pPresentationParameters,
3447 IDirect3D9 *pD3D9,
3448 ID3DPresentGroup *pPresentationGroup,
3449 struct d3dadapter9_context *pCTX,
3450 boolean ex,
3451 D3DDISPLAYMODEEX *pFullscreenDisplayMode,
3452 struct NineDevice9 **ppOut )
3453 {
3454 BOOL lock;
3455 lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED);
3456
3457 NINE_NEW(Device9, ppOut, lock, /* args */
3458 pScreen, pCreationParameters, pCaps,
3459 pPresentationParameters, pD3D9, pPresentationGroup, pCTX,
3460 ex, pFullscreenDisplayMode);
3461 }