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