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