st/nine: Align stack for entry points
[mesa.git] / src / gallium / state_trackers / nine / surface9.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 "surface9.h"
24 #include "device9.h"
25
26 /* for marking dirty */
27 #include "basetexture9.h"
28 #include "texture9.h"
29 #include "cubetexture9.h"
30
31 #include "nine_helpers.h"
32 #include "nine_pipe.h"
33 #include "nine_dump.h"
34
35 #include "pipe/p_context.h"
36 #include "pipe/p_screen.h"
37 #include "pipe/p_state.h"
38
39 #include "util/u_math.h"
40 #include "util/u_inlines.h"
41 #include "util/u_surface.h"
42
43 #define DBG_CHANNEL DBG_SURFACE
44
45 #define is_ATI1_ATI2(format) (format == PIPE_FORMAT_RGTC1_UNORM || format == PIPE_FORMAT_RGTC2_UNORM)
46
47 HRESULT
48 NineSurface9_ctor( struct NineSurface9 *This,
49 struct NineUnknownParams *pParams,
50 struct NineUnknown *pContainer,
51 struct pipe_resource *pResource,
52 void *user_buffer,
53 uint8_t TextureType,
54 unsigned Level,
55 unsigned Layer,
56 D3DSURFACE_DESC *pDesc )
57 {
58 HRESULT hr;
59 union pipe_color_union rgba = {0};
60 struct pipe_surface *surf;
61 struct pipe_context *pipe = pParams->device->pipe;
62
63 DBG("This=%p pDevice=%p pResource=%p Level=%u Layer=%u pDesc=%p\n",
64 This, pParams->device, pResource, Level, Layer, pDesc);
65
66 /* Mark this as a special surface held by another internal resource. */
67 pParams->container = pContainer;
68
69 user_assert(!(pDesc->Usage & D3DUSAGE_DYNAMIC) ||
70 (pDesc->Pool != D3DPOOL_MANAGED), D3DERR_INVALIDCALL);
71
72 assert(pResource || (user_buffer && pDesc->Pool != D3DPOOL_DEFAULT) ||
73 (!pContainer && pDesc->Pool != D3DPOOL_DEFAULT) ||
74 pDesc->Format == D3DFMT_NULL);
75
76 assert(!pResource || !user_buffer);
77 assert(!user_buffer || pDesc->Pool != D3DPOOL_DEFAULT);
78 /* The only way we can have !pContainer is being created
79 * from create_zs_or_rt_surface with params 0 0 0 */
80 assert(pContainer || (Level == 0 && Layer == 0 && TextureType == 0));
81
82 This->data = (uint8_t *)user_buffer;
83
84 This->base.info.screen = pParams->device->screen;
85 This->base.info.target = PIPE_TEXTURE_2D;
86 This->base.info.width0 = pDesc->Width;
87 This->base.info.height0 = pDesc->Height;
88 This->base.info.depth0 = 1;
89 This->base.info.last_level = 0;
90 This->base.info.array_size = 1;
91 This->base.info.nr_samples = pDesc->MultiSampleType;
92 This->base.info.usage = PIPE_USAGE_DEFAULT;
93 This->base.info.bind = PIPE_BIND_SAMPLER_VIEW;
94 This->base.info.flags = 0;
95 This->base.info.format = d3d9_to_pipe_format_checked(This->base.info.screen,
96 pDesc->Format,
97 This->base.info.target,
98 This->base.info.nr_samples,
99 This->base.info.bind,
100 FALSE,
101 pDesc->Pool == D3DPOOL_SCRATCH);
102
103 if (pDesc->Usage & D3DUSAGE_RENDERTARGET)
104 This->base.info.bind |= PIPE_BIND_RENDER_TARGET;
105 if (pDesc->Usage & D3DUSAGE_DEPTHSTENCIL)
106 This->base.info.bind |= PIPE_BIND_DEPTH_STENCIL;
107
108 /* Ram buffer with no parent. Has to allocate the resource itself */
109 if (!pResource && !pContainer) {
110 assert(!user_buffer);
111 This->data = align_malloc(
112 nine_format_get_level_alloc_size(This->base.info.format,
113 pDesc->Width,
114 pDesc->Height,
115 0), 32);
116 if (!This->data)
117 return E_OUTOFMEMORY;
118 }
119
120 assert(pDesc->Pool != D3DPOOL_SYSTEMMEM || !pResource);
121
122 if (pResource && (pDesc->Usage & D3DUSAGE_DYNAMIC))
123 pResource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
124
125 hr = NineResource9_ctor(&This->base, pParams, pResource, FALSE, D3DRTYPE_SURFACE,
126 pDesc->Pool, pDesc->Usage);
127 if (FAILED(hr))
128 return hr;
129
130 This->pipe = This->base.base.device->pipe;
131 This->transfer = NULL;
132
133 This->texture = TextureType;
134 This->level = Level;
135 This->level_actual = Level;
136 This->layer = Layer;
137 This->desc = *pDesc;
138
139 This->stride = nine_format_get_stride(This->base.info.format, pDesc->Width);
140
141 if (pResource && NineSurface9_IsOffscreenPlain(This))
142 pResource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
143
144 /* TODO: investigate what else exactly needs to be cleared */
145 if (This->base.resource && (pDesc->Usage & D3DUSAGE_RENDERTARGET)) {
146 surf = NineSurface9_GetSurface(This, 0);
147 pipe->clear_render_target(pipe, surf, &rgba, 0, 0, pDesc->Width, pDesc->Height);
148 }
149
150 NineSurface9_Dump(This);
151
152 return D3D_OK;
153 }
154
155 void
156 NineSurface9_dtor( struct NineSurface9 *This )
157 {
158 if (This->transfer)
159 NineSurface9_UnlockRect(This);
160
161 pipe_surface_reference(&This->surface[0], NULL);
162 pipe_surface_reference(&This->surface[1], NULL);
163
164 /* Release system memory when we have to manage it (no parent) */
165 if (!This->base.base.container && This->data)
166 align_free(This->data);
167 NineResource9_dtor(&This->base);
168 }
169
170 struct pipe_surface *
171 NineSurface9_CreatePipeSurface( struct NineSurface9 *This, const int sRGB )
172 {
173 struct pipe_context *pipe = This->pipe;
174 struct pipe_screen *screen = pipe->screen;
175 struct pipe_resource *resource = This->base.resource;
176 struct pipe_surface templ;
177 enum pipe_format srgb_format;
178
179 assert(This->desc.Pool == D3DPOOL_DEFAULT);
180 assert(resource);
181
182 srgb_format = util_format_srgb(resource->format);
183 if (sRGB && srgb_format != PIPE_FORMAT_NONE &&
184 screen->is_format_supported(screen, srgb_format,
185 resource->target, 0, resource->bind))
186 templ.format = srgb_format;
187 else
188 templ.format = resource->format;
189 templ.u.tex.level = This->level;
190 templ.u.tex.first_layer = This->layer;
191 templ.u.tex.last_layer = This->layer;
192
193 This->surface[sRGB] = pipe->create_surface(pipe, resource, &templ);
194 assert(This->surface[sRGB]);
195 return This->surface[sRGB];
196 }
197
198 #ifdef DEBUG
199 void
200 NineSurface9_Dump( struct NineSurface9 *This )
201 {
202 struct NineBaseTexture9 *tex;
203 GUID id = IID_IDirect3DBaseTexture9;
204 REFIID ref = &id;
205
206 DBG("\nNineSurface9(%p->%p/%p): Pool=%s Type=%s Usage=%s\n"
207 "Dims=%ux%u Format=%s Stride=%u Lockable=%i\n"
208 "Level=%u(%u), Layer=%u\n", This, This->base.resource, This->data,
209 nine_D3DPOOL_to_str(This->desc.Pool),
210 nine_D3DRTYPE_to_str(This->desc.Type),
211 nine_D3DUSAGE_to_str(This->desc.Usage),
212 This->desc.Width, This->desc.Height,
213 d3dformat_to_string(This->desc.Format), This->stride,
214 This->base.resource &&
215 (This->base.resource->flags & NINE_RESOURCE_FLAG_LOCKABLE),
216 This->level, This->level_actual, This->layer);
217
218 if (!This->base.base.container)
219 return;
220 NineUnknown_QueryInterface(This->base.base.container, ref, (void **)&tex);
221 if (tex) {
222 NineBaseTexture9_Dump(tex);
223 NineUnknown_Release(NineUnknown(tex));
224 }
225 }
226 #endif /* DEBUG */
227
228 HRESULT NINE_WINAPI
229 NineSurface9_GetContainer( struct NineSurface9 *This,
230 REFIID riid,
231 void **ppContainer )
232 {
233 HRESULT hr;
234 if (!NineUnknown(This)->container)
235 return E_NOINTERFACE;
236 hr = NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer);
237 if (FAILED(hr))
238 DBG("QueryInterface FAILED!\n");
239 return hr;
240 }
241
242 void
243 NineSurface9_MarkContainerDirty( struct NineSurface9 *This )
244 {
245 if (This->texture) {
246 struct NineBaseTexture9 *tex =
247 NineBaseTexture9(This->base.base.container);
248 assert(tex);
249 assert(This->texture == D3DRTYPE_TEXTURE ||
250 This->texture == D3DRTYPE_CUBETEXTURE);
251 if (This->base.pool == D3DPOOL_MANAGED)
252 tex->managed.dirty = TRUE;
253 else
254 if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP)
255 tex->dirty_mip = TRUE;
256
257 BASETEX_REGISTER_UPDATE(tex);
258 }
259 }
260
261 HRESULT NINE_WINAPI
262 NineSurface9_GetDesc( struct NineSurface9 *This,
263 D3DSURFACE_DESC *pDesc )
264 {
265 user_assert(pDesc != NULL, E_POINTER);
266 *pDesc = This->desc;
267 return D3D_OK;
268 }
269
270 /* Add the dirty rects to the source texture */
271 inline void
272 NineSurface9_AddDirtyRect( struct NineSurface9 *This,
273 const struct pipe_box *box )
274 {
275 RECT dirty_rect;
276
277 DBG("This=%p box=%p\n", This, box);
278
279 assert (This->base.pool != D3DPOOL_MANAGED ||
280 This->texture == D3DRTYPE_CUBETEXTURE ||
281 This->texture == D3DRTYPE_TEXTURE);
282
283 if (This->base.pool == D3DPOOL_DEFAULT)
284 return;
285
286 /* Add a dirty rect to level 0 of the parent texture */
287 dirty_rect.left = box->x << This->level_actual;
288 dirty_rect.right = dirty_rect.left + (box->width << This->level_actual);
289 dirty_rect.top = box->y << This->level_actual;
290 dirty_rect.bottom = dirty_rect.top + (box->height << This->level_actual);
291
292 if (This->texture == D3DRTYPE_TEXTURE) {
293 struct NineTexture9 *tex =
294 NineTexture9(This->base.base.container);
295
296 NineTexture9_AddDirtyRect(tex, &dirty_rect);
297 } else if (This->texture == D3DRTYPE_CUBETEXTURE) {
298 struct NineCubeTexture9 *ctex =
299 NineCubeTexture9(This->base.base.container);
300
301 NineCubeTexture9_AddDirtyRect(ctex, This->layer, &dirty_rect);
302 }
303 }
304
305 static inline uint8_t *
306 NineSurface9_GetSystemMemPointer(struct NineSurface9 *This, int x, int y)
307 {
308 unsigned x_offset = util_format_get_stride(This->base.info.format, x);
309
310 y = util_format_get_nblocksy(This->base.info.format, y);
311
312 assert(This->data);
313 return This->data + (y * This->stride + x_offset);
314 }
315
316 HRESULT NINE_WINAPI
317 NineSurface9_LockRect( struct NineSurface9 *This,
318 D3DLOCKED_RECT *pLockedRect,
319 const RECT *pRect,
320 DWORD Flags )
321 {
322 struct pipe_resource *resource = This->base.resource;
323 struct pipe_box box;
324 unsigned usage;
325
326 DBG("This=%p pLockedRect=%p pRect=%p[%u..%u,%u..%u] Flags=%s\n", This,
327 pLockedRect, pRect,
328 pRect ? pRect->left : 0, pRect ? pRect->right : 0,
329 pRect ? pRect->top : 0, pRect ? pRect->bottom : 0,
330 nine_D3DLOCK_to_str(Flags));
331 NineSurface9_Dump(This);
332
333 /* check if it's already locked */
334 user_assert(This->lock_count == 0, D3DERR_INVALIDCALL);
335
336 /* set pBits to NULL after lock_count check */
337 user_assert(pLockedRect, E_POINTER);
338 pLockedRect->pBits = NULL;
339
340 #ifdef NINE_STRICT
341 user_assert(This->base.pool != D3DPOOL_DEFAULT ||
342 (resource && (resource->flags & NINE_RESOURCE_FLAG_LOCKABLE)),
343 D3DERR_INVALIDCALL);
344 #endif
345 user_assert(!(Flags & ~(D3DLOCK_DISCARD |
346 D3DLOCK_DONOTWAIT |
347 D3DLOCK_NO_DIRTY_UPDATE |
348 D3DLOCK_NOOVERWRITE |
349 D3DLOCK_NOSYSLOCK | /* ignored */
350 D3DLOCK_READONLY)), D3DERR_INVALIDCALL);
351 user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)),
352 D3DERR_INVALIDCALL);
353
354 user_assert(This->desc.MultiSampleType == D3DMULTISAMPLE_NONE,
355 D3DERR_INVALIDCALL);
356
357 if (pRect && This->desc.Pool == D3DPOOL_DEFAULT &&
358 util_format_is_compressed(This->base.info.format)) {
359 const unsigned w = util_format_get_blockwidth(This->base.info.format);
360 const unsigned h = util_format_get_blockheight(This->base.info.format);
361 user_assert((pRect->left == 0 && pRect->right == This->desc.Width &&
362 pRect->top == 0 && pRect->bottom == This->desc.Height) ||
363 (!(pRect->left % w) && !(pRect->right % w) &&
364 !(pRect->top % h) && !(pRect->bottom % h)),
365 D3DERR_INVALIDCALL);
366 }
367
368 if (Flags & D3DLOCK_DISCARD) {
369 usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE;
370 } else {
371 usage = (Flags & D3DLOCK_READONLY) ?
372 PIPE_TRANSFER_READ : PIPE_TRANSFER_READ_WRITE;
373 }
374 if (Flags & D3DLOCK_DONOTWAIT)
375 usage |= PIPE_TRANSFER_DONTBLOCK;
376
377 if (pRect) {
378 /* Windows XP accepts invalid locking rectangles, Windows 7 rejects
379 * them. Use Windows XP behaviour for now. */
380 rect_to_pipe_box(&box, pRect);
381 } else {
382 u_box_origin_2d(This->desc.Width, This->desc.Height, &box);
383 }
384
385 user_warn(This->desc.Format == D3DFMT_NULL);
386
387 if (This->data) {
388 DBG("returning system memory\n");
389 /* ATI1 and ATI2 need special handling, because of d3d9 bug.
390 * We must advertise to the application as if it is uncompressed
391 * and bpp 8, and the app has a workaround to work with the fact
392 * that it is actually compressed. */
393 if (is_ATI1_ATI2(This->base.info.format)) {
394 pLockedRect->Pitch = This->desc.Width;
395 pLockedRect->pBits = This->data + box.y * This->desc.Width + box.x;
396 } else {
397 pLockedRect->Pitch = This->stride;
398 pLockedRect->pBits = NineSurface9_GetSystemMemPointer(This,
399 box.x,
400 box.y);
401 }
402 } else {
403 DBG("mapping pipe_resource %p (level=%u usage=%x)\n",
404 resource, This->level, usage);
405
406 pLockedRect->pBits = This->pipe->transfer_map(This->pipe, resource,
407 This->level, usage, &box,
408 &This->transfer);
409 if (!This->transfer) {
410 DBG("transfer_map failed\n");
411 if (Flags & D3DLOCK_DONOTWAIT)
412 return D3DERR_WASSTILLDRAWING;
413 return D3DERR_INVALIDCALL;
414 }
415 pLockedRect->Pitch = This->transfer->stride;
416 }
417
418 if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) {
419 NineSurface9_MarkContainerDirty(This);
420 NineSurface9_AddDirtyRect(This, &box);
421 }
422
423 ++This->lock_count;
424 return D3D_OK;
425 }
426
427 HRESULT NINE_WINAPI
428 NineSurface9_UnlockRect( struct NineSurface9 *This )
429 {
430 DBG("This=%p lock_count=%u\n", This, This->lock_count);
431 user_assert(This->lock_count, D3DERR_INVALIDCALL);
432 if (This->transfer) {
433 This->pipe->transfer_unmap(This->pipe, This->transfer);
434 This->transfer = NULL;
435 }
436 --This->lock_count;
437 return D3D_OK;
438 }
439
440 HRESULT NINE_WINAPI
441 NineSurface9_GetDC( struct NineSurface9 *This,
442 HDC *phdc )
443 {
444 STUB(D3DERR_INVALIDCALL);
445 }
446
447 HRESULT NINE_WINAPI
448 NineSurface9_ReleaseDC( struct NineSurface9 *This,
449 HDC hdc )
450 {
451 STUB(D3DERR_INVALIDCALL);
452 }
453
454 IDirect3DSurface9Vtbl NineSurface9_vtable = {
455 (void *)NineUnknown_QueryInterface,
456 (void *)NineUnknown_AddRef,
457 (void *)NineUnknown_Release,
458 (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
459 (void *)NineResource9_SetPrivateData,
460 (void *)NineResource9_GetPrivateData,
461 (void *)NineResource9_FreePrivateData,
462 (void *)NineResource9_SetPriority,
463 (void *)NineResource9_GetPriority,
464 (void *)NineResource9_PreLoad,
465 (void *)NineResource9_GetType,
466 (void *)NineSurface9_GetContainer,
467 (void *)NineSurface9_GetDesc,
468 (void *)NineSurface9_LockRect,
469 (void *)NineSurface9_UnlockRect,
470 (void *)NineSurface9_GetDC,
471 (void *)NineSurface9_ReleaseDC
472 };
473
474 /* When this function is called, we have already checked
475 * The copy regions fit the surfaces */
476 void
477 NineSurface9_CopyMemToDefault( struct NineSurface9 *This,
478 struct NineSurface9 *From,
479 const POINT *pDestPoint,
480 const RECT *pSourceRect )
481 {
482 struct pipe_context *pipe = This->pipe;
483 struct pipe_resource *r_dst = This->base.resource;
484 struct pipe_box dst_box;
485 const uint8_t *p_src;
486 int src_x, src_y, dst_x, dst_y, copy_width, copy_height;
487
488 assert(This->base.pool == D3DPOOL_DEFAULT &&
489 From->base.pool == D3DPOOL_SYSTEMMEM);
490
491 if (pDestPoint) {
492 dst_x = pDestPoint->x;
493 dst_y = pDestPoint->y;
494 } else {
495 dst_x = 0;
496 dst_y = 0;
497 }
498
499 if (pSourceRect) {
500 src_x = pSourceRect->left;
501 src_y = pSourceRect->top;
502 copy_width = pSourceRect->right - pSourceRect->left;
503 copy_height = pSourceRect->bottom - pSourceRect->top;
504 } else {
505 src_x = 0;
506 src_y = 0;
507 copy_width = From->desc.Width;
508 copy_height = From->desc.Height;
509 }
510
511 u_box_2d_zslice(dst_x, dst_y, This->layer,
512 copy_width, copy_height, &dst_box);
513
514 p_src = NineSurface9_GetSystemMemPointer(From, src_x, src_y);
515
516 pipe->transfer_inline_write(pipe, r_dst, This->level,
517 0, /* WRITE|DISCARD are implicit */
518 &dst_box, p_src, From->stride, 0);
519
520 NineSurface9_MarkContainerDirty(This);
521 }
522
523 void
524 NineSurface9_CopyDefaultToMem( struct NineSurface9 *This,
525 struct NineSurface9 *From )
526 {
527 struct pipe_context *pipe = This->pipe;
528 struct pipe_resource *r_src = From->base.resource;
529 struct pipe_transfer *transfer;
530 struct pipe_box src_box;
531 uint8_t *p_dst;
532 const uint8_t *p_src;
533
534 assert(This->base.pool == D3DPOOL_SYSTEMMEM &&
535 From->base.pool == D3DPOOL_DEFAULT);
536
537 assert(This->desc.Width == From->desc.Width);
538 assert(This->desc.Height == From->desc.Height);
539
540 u_box_origin_2d(This->desc.Width, This->desc.Height, &src_box);
541 src_box.z = From->layer;
542
543 p_src = pipe->transfer_map(pipe, r_src, From->level,
544 PIPE_TRANSFER_READ,
545 &src_box, &transfer);
546 p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0);
547
548 assert (p_src && p_dst);
549
550 util_copy_rect(p_dst, This->base.info.format,
551 This->stride, 0, 0,
552 This->desc.Width, This->desc.Height,
553 p_src,
554 transfer->stride, 0, 0);
555
556 pipe->transfer_unmap(pipe, transfer);
557 }
558
559
560 /* Gladly, rendering to a MANAGED surface is not permitted, so we will
561 * never have to do the reverse, i.e. download the surface.
562 */
563 HRESULT
564 NineSurface9_UploadSelf( struct NineSurface9 *This,
565 const struct pipe_box *damaged )
566 {
567 struct pipe_context *pipe = This->pipe;
568 struct pipe_resource *res = This->base.resource;
569 uint8_t *ptr;
570 struct pipe_box box;
571
572 DBG("This=%p damaged=%p\n", This, damaged);
573
574 assert(This->base.pool == D3DPOOL_MANAGED);
575
576 if (damaged) {
577 box = *damaged;
578 box.z = This->layer;
579 box.depth = 1;
580 } else {
581 box.x = 0;
582 box.y = 0;
583 box.z = This->layer;
584 box.width = This->desc.Width;
585 box.height = This->desc.Height;
586 box.depth = 1;
587 }
588
589 ptr = NineSurface9_GetSystemMemPointer(This, box.x, box.y);
590
591 pipe->transfer_inline_write(pipe, res, This->level, 0,
592 &box, ptr, This->stride, 0);
593
594 return D3D_OK;
595 }
596
597 void
598 NineSurface9_SetResourceResize( struct NineSurface9 *This,
599 struct pipe_resource *resource )
600 {
601 assert(This->level == 0 && This->level_actual == 0);
602 assert(!This->lock_count);
603 assert(This->desc.Pool == D3DPOOL_DEFAULT);
604 assert(!This->texture);
605
606 pipe_resource_reference(&This->base.resource, resource);
607
608 This->desc.Width = This->base.info.width0 = resource->width0;
609 This->desc.Height = This->base.info.height0 = resource->height0;
610 This->desc.MultiSampleType = This->base.info.nr_samples = resource->nr_samples;
611
612 This->stride = nine_format_get_stride(This->base.info.format,
613 This->desc.Width);
614
615 pipe_surface_reference(&This->surface[0], NULL);
616 pipe_surface_reference(&This->surface[1], NULL);
617 }
618
619
620 static const GUID *NineSurface9_IIDs[] = {
621 &IID_IDirect3DSurface9,
622 &IID_IDirect3DResource9,
623 &IID_IUnknown,
624 NULL
625 };
626
627 HRESULT
628 NineSurface9_new( struct NineDevice9 *pDevice,
629 struct NineUnknown *pContainer,
630 struct pipe_resource *pResource,
631 void *user_buffer,
632 uint8_t TextureType,
633 unsigned Level,
634 unsigned Layer,
635 D3DSURFACE_DESC *pDesc,
636 struct NineSurface9 **ppOut )
637 {
638 NINE_DEVICE_CHILD_NEW(Surface9, ppOut, pDevice, /* args */
639 pContainer, pResource, user_buffer,
640 TextureType, Level, Layer, pDesc);
641 }