gallium/util: don't modify usage in pipe_buffer_write
[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 /* Get true format */
109 This->format_conversion = d3d9_to_pipe_format_checked(This->base.info.screen,
110 pDesc->Format,
111 This->base.info.target,
112 This->base.info.nr_samples,
113 This->base.info.bind,
114 FALSE,
115 TRUE);
116 if (This->base.info.format != This->format_conversion) {
117 This->data_conversion = align_malloc(
118 nine_format_get_level_alloc_size(This->format_conversion,
119 pDesc->Width,
120 pDesc->Height,
121 0), 32);
122 if (!This->data_conversion)
123 return E_OUTOFMEMORY;
124 This->stride_conversion = nine_format_get_stride(This->format_conversion,
125 pDesc->Width);
126 }
127
128 /* Ram buffer with no parent. Has to allocate the resource itself */
129 if (!pResource && !pContainer) {
130 assert(!user_buffer);
131 This->data = align_malloc(
132 nine_format_get_level_alloc_size(This->base.info.format,
133 pDesc->Width,
134 pDesc->Height,
135 0), 32);
136 if (!This->data)
137 return E_OUTOFMEMORY;
138 }
139
140 assert(pDesc->Pool != D3DPOOL_SYSTEMMEM || !pResource);
141
142 if (pResource && (pDesc->Usage & D3DUSAGE_DYNAMIC))
143 pResource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
144
145 hr = NineResource9_ctor(&This->base, pParams, pResource, FALSE, D3DRTYPE_SURFACE,
146 pDesc->Pool, pDesc->Usage);
147 if (FAILED(hr))
148 return hr;
149
150 This->pipe = This->base.base.device->pipe;
151 This->transfer = NULL;
152
153 This->texture = TextureType;
154 This->level = Level;
155 This->level_actual = Level;
156 This->layer = Layer;
157 This->desc = *pDesc;
158
159 This->stride = nine_format_get_stride(This->base.info.format, pDesc->Width);
160
161 if (pResource && NineSurface9_IsOffscreenPlain(This))
162 pResource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
163
164 /* TODO: investigate what else exactly needs to be cleared */
165 if (This->base.resource && (pDesc->Usage & D3DUSAGE_RENDERTARGET)) {
166 surf = NineSurface9_GetSurface(This, 0);
167 pipe->clear_render_target(pipe, surf, &rgba, 0, 0, pDesc->Width, pDesc->Height);
168 }
169
170 NineSurface9_Dump(This);
171
172 return D3D_OK;
173 }
174
175 void
176 NineSurface9_dtor( struct NineSurface9 *This )
177 {
178 DBG("This=%p\n", This);
179
180 if (This->transfer)
181 NineSurface9_UnlockRect(This);
182
183 pipe_surface_reference(&This->surface[0], NULL);
184 pipe_surface_reference(&This->surface[1], NULL);
185
186 /* Release system memory when we have to manage it (no parent) */
187 if (!This->base.base.container && This->data)
188 align_free(This->data);
189 if (This->data_conversion)
190 align_free(This->data_conversion);
191 NineResource9_dtor(&This->base);
192 }
193
194 struct pipe_surface *
195 NineSurface9_CreatePipeSurface( struct NineSurface9 *This, const int sRGB )
196 {
197 struct pipe_context *pipe = This->pipe;
198 struct pipe_screen *screen = pipe->screen;
199 struct pipe_resource *resource = This->base.resource;
200 struct pipe_surface templ;
201 enum pipe_format srgb_format;
202
203 assert(This->desc.Pool == D3DPOOL_DEFAULT);
204 assert(resource);
205
206 srgb_format = util_format_srgb(resource->format);
207 if (sRGB && srgb_format != PIPE_FORMAT_NONE &&
208 screen->is_format_supported(screen, srgb_format,
209 resource->target, 0, resource->bind))
210 templ.format = srgb_format;
211 else
212 templ.format = resource->format;
213 templ.u.tex.level = This->level;
214 templ.u.tex.first_layer = This->layer;
215 templ.u.tex.last_layer = This->layer;
216
217 This->surface[sRGB] = pipe->create_surface(pipe, resource, &templ);
218 assert(This->surface[sRGB]);
219 return This->surface[sRGB];
220 }
221
222 #ifdef DEBUG
223 void
224 NineSurface9_Dump( struct NineSurface9 *This )
225 {
226 struct NineBaseTexture9 *tex;
227 GUID id = IID_IDirect3DBaseTexture9;
228 REFIID ref = &id;
229
230 DBG("\nNineSurface9(%p->%p/%p): Pool=%s Type=%s Usage=%s\n"
231 "Dims=%ux%u Format=%s Stride=%u Lockable=%i\n"
232 "Level=%u(%u), Layer=%u\n", This, This->base.resource, This->data,
233 nine_D3DPOOL_to_str(This->desc.Pool),
234 nine_D3DRTYPE_to_str(This->desc.Type),
235 nine_D3DUSAGE_to_str(This->desc.Usage),
236 This->desc.Width, This->desc.Height,
237 d3dformat_to_string(This->desc.Format), This->stride,
238 This->base.resource &&
239 (This->base.resource->flags & NINE_RESOURCE_FLAG_LOCKABLE),
240 This->level, This->level_actual, This->layer);
241
242 if (!This->base.base.container)
243 return;
244 NineUnknown_QueryInterface(This->base.base.container, ref, (void **)&tex);
245 if (tex) {
246 NineBaseTexture9_Dump(tex);
247 NineUnknown_Release(NineUnknown(tex));
248 }
249 }
250 #endif /* DEBUG */
251
252 HRESULT NINE_WINAPI
253 NineSurface9_GetContainer( struct NineSurface9 *This,
254 REFIID riid,
255 void **ppContainer )
256 {
257 HRESULT hr;
258 if (!NineUnknown(This)->container)
259 return E_NOINTERFACE;
260 hr = NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer);
261 if (FAILED(hr))
262 DBG("QueryInterface FAILED!\n");
263 return hr;
264 }
265
266 void
267 NineSurface9_MarkContainerDirty( struct NineSurface9 *This )
268 {
269 if (This->texture) {
270 struct NineBaseTexture9 *tex =
271 NineBaseTexture9(This->base.base.container);
272 assert(tex);
273 assert(This->texture == D3DRTYPE_TEXTURE ||
274 This->texture == D3DRTYPE_CUBETEXTURE);
275 if (This->base.pool == D3DPOOL_MANAGED)
276 tex->managed.dirty = TRUE;
277 else
278 if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP)
279 tex->dirty_mip = TRUE;
280
281 BASETEX_REGISTER_UPDATE(tex);
282 }
283 }
284
285 HRESULT NINE_WINAPI
286 NineSurface9_GetDesc( struct NineSurface9 *This,
287 D3DSURFACE_DESC *pDesc )
288 {
289 user_assert(pDesc != NULL, E_POINTER);
290 *pDesc = This->desc;
291 return D3D_OK;
292 }
293
294 /* Add the dirty rects to the source texture */
295 inline void
296 NineSurface9_AddDirtyRect( struct NineSurface9 *This,
297 const struct pipe_box *box )
298 {
299 RECT dirty_rect;
300
301 DBG("This=%p box=%p\n", This, box);
302
303 assert (This->base.pool != D3DPOOL_MANAGED ||
304 This->texture == D3DRTYPE_CUBETEXTURE ||
305 This->texture == D3DRTYPE_TEXTURE);
306
307 if (This->base.pool == D3DPOOL_DEFAULT)
308 return;
309
310 /* Add a dirty rect to level 0 of the parent texture */
311 dirty_rect.left = box->x << This->level_actual;
312 dirty_rect.right = dirty_rect.left + (box->width << This->level_actual);
313 dirty_rect.top = box->y << This->level_actual;
314 dirty_rect.bottom = dirty_rect.top + (box->height << This->level_actual);
315
316 if (This->texture == D3DRTYPE_TEXTURE) {
317 struct NineTexture9 *tex =
318 NineTexture9(This->base.base.container);
319
320 NineTexture9_AddDirtyRect(tex, &dirty_rect);
321 } else if (This->texture == D3DRTYPE_CUBETEXTURE) {
322 struct NineCubeTexture9 *ctex =
323 NineCubeTexture9(This->base.base.container);
324
325 NineCubeTexture9_AddDirtyRect(ctex, This->layer, &dirty_rect);
326 }
327 }
328
329 static inline uint8_t *
330 NineSurface9_GetSystemMemPointer(struct NineSurface9 *This, int x, int y)
331 {
332 unsigned x_offset = util_format_get_stride(This->base.info.format, x);
333
334 y = util_format_get_nblocksy(This->base.info.format, y);
335
336 assert(This->data);
337 return This->data + (y * This->stride + x_offset);
338 }
339
340 HRESULT NINE_WINAPI
341 NineSurface9_LockRect( struct NineSurface9 *This,
342 D3DLOCKED_RECT *pLockedRect,
343 const RECT *pRect,
344 DWORD Flags )
345 {
346 struct pipe_resource *resource = This->base.resource;
347 struct pipe_box box;
348 unsigned usage;
349
350 DBG("This=%p pLockedRect=%p pRect=%p[%u..%u,%u..%u] Flags=%s\n", This,
351 pLockedRect, pRect,
352 pRect ? pRect->left : 0, pRect ? pRect->right : 0,
353 pRect ? pRect->top : 0, pRect ? pRect->bottom : 0,
354 nine_D3DLOCK_to_str(Flags));
355 NineSurface9_Dump(This);
356
357 /* check if it's already locked */
358 user_assert(This->lock_count == 0, D3DERR_INVALIDCALL);
359
360 /* set pBits to NULL after lock_count check */
361 user_assert(pLockedRect, E_POINTER);
362 pLockedRect->pBits = NULL;
363
364 #ifdef NINE_STRICT
365 user_assert(This->base.pool != D3DPOOL_DEFAULT ||
366 (resource && (resource->flags & NINE_RESOURCE_FLAG_LOCKABLE)),
367 D3DERR_INVALIDCALL);
368 #endif
369 user_assert(!(Flags & ~(D3DLOCK_DISCARD |
370 D3DLOCK_DONOTWAIT |
371 D3DLOCK_NO_DIRTY_UPDATE |
372 D3DLOCK_NOOVERWRITE |
373 D3DLOCK_NOSYSLOCK | /* ignored */
374 D3DLOCK_READONLY)), D3DERR_INVALIDCALL);
375 user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)),
376 D3DERR_INVALIDCALL);
377
378 user_assert(This->desc.MultiSampleType == D3DMULTISAMPLE_NONE,
379 D3DERR_INVALIDCALL);
380
381 if (pRect && This->desc.Pool == D3DPOOL_DEFAULT &&
382 util_format_is_compressed(This->base.info.format)) {
383 const unsigned w = util_format_get_blockwidth(This->base.info.format);
384 const unsigned h = util_format_get_blockheight(This->base.info.format);
385 user_assert((pRect->left == 0 && pRect->right == This->desc.Width &&
386 pRect->top == 0 && pRect->bottom == This->desc.Height) ||
387 (!(pRect->left % w) && !(pRect->right % w) &&
388 !(pRect->top % h) && !(pRect->bottom % h)),
389 D3DERR_INVALIDCALL);
390 }
391
392 if (Flags & D3DLOCK_DISCARD) {
393 usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE;
394 } else {
395 usage = (Flags & D3DLOCK_READONLY) ?
396 PIPE_TRANSFER_READ : PIPE_TRANSFER_READ_WRITE;
397 }
398 if (Flags & D3DLOCK_DONOTWAIT)
399 usage |= PIPE_TRANSFER_DONTBLOCK;
400
401 if (pRect) {
402 /* Windows XP accepts invalid locking rectangles, Windows 7 rejects
403 * them. Use Windows XP behaviour for now. */
404 rect_to_pipe_box(&box, pRect);
405 } else {
406 u_box_origin_2d(This->desc.Width, This->desc.Height, &box);
407 }
408
409 user_warn(This->desc.Format == D3DFMT_NULL);
410
411 if (This->data_conversion) {
412 /* For now we only have uncompressed formats here */
413 pLockedRect->Pitch = This->stride_conversion;
414 pLockedRect->pBits = This->data_conversion + box.y * This->stride_conversion +
415 util_format_get_stride(This->format_conversion, box.x);
416 } else if (This->data) {
417 DBG("returning system memory\n");
418 /* ATI1 and ATI2 need special handling, because of d3d9 bug.
419 * We must advertise to the application as if it is uncompressed
420 * and bpp 8, and the app has a workaround to work with the fact
421 * that it is actually compressed. */
422 if (is_ATI1_ATI2(This->base.info.format)) {
423 pLockedRect->Pitch = This->desc.Width;
424 pLockedRect->pBits = This->data + box.y * This->desc.Width + box.x;
425 } else {
426 pLockedRect->Pitch = This->stride;
427 pLockedRect->pBits = NineSurface9_GetSystemMemPointer(This,
428 box.x,
429 box.y);
430 }
431 } else {
432 DBG("mapping pipe_resource %p (level=%u usage=%x)\n",
433 resource, This->level, usage);
434
435 pLockedRect->pBits = This->pipe->transfer_map(This->pipe, resource,
436 This->level, usage, &box,
437 &This->transfer);
438 if (!This->transfer) {
439 DBG("transfer_map failed\n");
440 if (Flags & D3DLOCK_DONOTWAIT)
441 return D3DERR_WASSTILLDRAWING;
442 return D3DERR_INVALIDCALL;
443 }
444 pLockedRect->Pitch = This->transfer->stride;
445 }
446
447 if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) {
448 NineSurface9_MarkContainerDirty(This);
449 NineSurface9_AddDirtyRect(This, &box);
450 }
451
452 ++This->lock_count;
453 return D3D_OK;
454 }
455
456 HRESULT NINE_WINAPI
457 NineSurface9_UnlockRect( struct NineSurface9 *This )
458 {
459 DBG("This=%p lock_count=%u\n", This, This->lock_count);
460 user_assert(This->lock_count, D3DERR_INVALIDCALL);
461 if (This->transfer) {
462 This->pipe->transfer_unmap(This->pipe, This->transfer);
463 This->transfer = NULL;
464 }
465 --This->lock_count;
466
467 if (This->data_conversion) {
468 struct pipe_transfer *transfer;
469 uint8_t *dst = This->data;
470 struct pipe_box box;
471
472 u_box_origin_2d(This->desc.Width, This->desc.Height, &box);
473
474 if (!dst) {
475 dst = This->pipe->transfer_map(This->pipe,
476 This->base.resource,
477 This->level,
478 PIPE_TRANSFER_WRITE |
479 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
480 &box, &transfer);
481 if (!dst)
482 return D3D_OK;
483 }
484
485 (void) util_format_translate(This->base.info.format,
486 dst, This->data ? This->stride : transfer->stride,
487 0, 0,
488 This->format_conversion,
489 This->data_conversion,
490 This->stride_conversion,
491 0, 0,
492 This->desc.Width, This->desc.Height);
493
494 if (!This->data)
495 pipe_transfer_unmap(This->pipe, transfer);
496 }
497 return D3D_OK;
498 }
499
500 HRESULT NINE_WINAPI
501 NineSurface9_GetDC( struct NineSurface9 *This,
502 HDC *phdc )
503 {
504 STUB(D3DERR_INVALIDCALL);
505 }
506
507 HRESULT NINE_WINAPI
508 NineSurface9_ReleaseDC( struct NineSurface9 *This,
509 HDC hdc )
510 {
511 STUB(D3DERR_INVALIDCALL);
512 }
513
514 IDirect3DSurface9Vtbl NineSurface9_vtable = {
515 (void *)NineUnknown_QueryInterface,
516 (void *)NineUnknown_AddRef,
517 (void *)NineUnknown_Release,
518 (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
519 (void *)NineResource9_SetPrivateData,
520 (void *)NineResource9_GetPrivateData,
521 (void *)NineResource9_FreePrivateData,
522 (void *)NineResource9_SetPriority,
523 (void *)NineResource9_GetPriority,
524 (void *)NineResource9_PreLoad,
525 (void *)NineResource9_GetType,
526 (void *)NineSurface9_GetContainer,
527 (void *)NineSurface9_GetDesc,
528 (void *)NineSurface9_LockRect,
529 (void *)NineSurface9_UnlockRect,
530 (void *)NineSurface9_GetDC,
531 (void *)NineSurface9_ReleaseDC
532 };
533
534 /* When this function is called, we have already checked
535 * The copy regions fit the surfaces */
536 void
537 NineSurface9_CopyMemToDefault( struct NineSurface9 *This,
538 struct NineSurface9 *From,
539 const POINT *pDestPoint,
540 const RECT *pSourceRect )
541 {
542 struct pipe_context *pipe = This->pipe;
543 struct pipe_transfer *transfer = NULL;
544 struct pipe_resource *r_dst = This->base.resource;
545 struct pipe_box dst_box;
546 uint8_t *map = NULL;
547 int src_x, src_y, dst_x, dst_y, copy_width, copy_height;
548
549 assert(This->base.pool == D3DPOOL_DEFAULT &&
550 From->base.pool == D3DPOOL_SYSTEMMEM);
551
552 if (pDestPoint) {
553 dst_x = pDestPoint->x;
554 dst_y = pDestPoint->y;
555 } else {
556 dst_x = 0;
557 dst_y = 0;
558 }
559
560 if (pSourceRect) {
561 src_x = pSourceRect->left;
562 src_y = pSourceRect->top;
563 copy_width = pSourceRect->right - pSourceRect->left;
564 copy_height = pSourceRect->bottom - pSourceRect->top;
565 } else {
566 src_x = 0;
567 src_y = 0;
568 copy_width = From->desc.Width;
569 copy_height = From->desc.Height;
570 }
571
572 u_box_2d_zslice(dst_x, dst_y, This->layer,
573 copy_width, copy_height, &dst_box);
574
575 map = pipe->transfer_map(pipe,
576 r_dst,
577 This->level,
578 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
579 &dst_box, &transfer);
580 if (!map)
581 return;
582
583 /* Note: if formats are the sames, it will revert
584 * to normal memcpy */
585 (void) util_format_translate(r_dst->format,
586 map, transfer->stride,
587 0, 0,
588 From->base.info.format,
589 From->data, From->stride,
590 src_x, src_y,
591 copy_width, copy_height);
592
593 pipe_transfer_unmap(pipe, transfer);
594
595 if (This->data_conversion)
596 (void) util_format_translate(This->format_conversion,
597 This->data_conversion,
598 This->stride_conversion,
599 dst_x, dst_y,
600 From->base.info.format,
601 From->data, From->stride,
602 src_x, src_y,
603 copy_width, copy_height);
604
605 NineSurface9_MarkContainerDirty(This);
606 }
607
608 void
609 NineSurface9_CopyDefaultToMem( struct NineSurface9 *This,
610 struct NineSurface9 *From )
611 {
612 struct pipe_context *pipe = This->pipe;
613 struct pipe_resource *r_src = From->base.resource;
614 struct pipe_transfer *transfer;
615 struct pipe_box src_box;
616 uint8_t *p_dst;
617 const uint8_t *p_src;
618
619 assert(This->base.pool == D3DPOOL_SYSTEMMEM &&
620 From->base.pool == D3DPOOL_DEFAULT);
621
622 assert(This->desc.Width == From->desc.Width);
623 assert(This->desc.Height == From->desc.Height);
624
625 u_box_origin_2d(This->desc.Width, This->desc.Height, &src_box);
626 src_box.z = From->layer;
627
628 p_src = pipe->transfer_map(pipe, r_src, From->level,
629 PIPE_TRANSFER_READ,
630 &src_box, &transfer);
631 p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0);
632
633 assert (p_src && p_dst);
634
635 util_copy_rect(p_dst, This->base.info.format,
636 This->stride, 0, 0,
637 This->desc.Width, This->desc.Height,
638 p_src,
639 transfer->stride, 0, 0);
640
641 pipe->transfer_unmap(pipe, transfer);
642 }
643
644
645 /* Gladly, rendering to a MANAGED surface is not permitted, so we will
646 * never have to do the reverse, i.e. download the surface.
647 */
648 HRESULT
649 NineSurface9_UploadSelf( struct NineSurface9 *This,
650 const struct pipe_box *damaged )
651 {
652 struct pipe_context *pipe = This->pipe;
653 struct pipe_resource *res = This->base.resource;
654 uint8_t *ptr;
655 struct pipe_box box;
656
657 DBG("This=%p damaged=%p\n", This, damaged);
658
659 assert(This->base.pool == D3DPOOL_MANAGED);
660
661 if (damaged) {
662 box = *damaged;
663 box.z = This->layer;
664 box.depth = 1;
665 } else {
666 box.x = 0;
667 box.y = 0;
668 box.z = This->layer;
669 box.width = This->desc.Width;
670 box.height = This->desc.Height;
671 box.depth = 1;
672 }
673
674 ptr = NineSurface9_GetSystemMemPointer(This, box.x, box.y);
675
676 pipe->texture_subdata(pipe, res, This->level, 0,
677 &box, ptr, This->stride, 0);
678
679 return D3D_OK;
680 }
681
682 void
683 NineSurface9_SetResourceResize( struct NineSurface9 *This,
684 struct pipe_resource *resource )
685 {
686 assert(This->level == 0 && This->level_actual == 0);
687 assert(!This->lock_count);
688 assert(This->desc.Pool == D3DPOOL_DEFAULT);
689 assert(!This->texture);
690
691 pipe_resource_reference(&This->base.resource, resource);
692
693 This->desc.Width = This->base.info.width0 = resource->width0;
694 This->desc.Height = This->base.info.height0 = resource->height0;
695 This->desc.MultiSampleType = This->base.info.nr_samples = resource->nr_samples;
696
697 This->stride = nine_format_get_stride(This->base.info.format,
698 This->desc.Width);
699
700 pipe_surface_reference(&This->surface[0], NULL);
701 pipe_surface_reference(&This->surface[1], NULL);
702 }
703
704
705 static const GUID *NineSurface9_IIDs[] = {
706 &IID_IDirect3DSurface9,
707 &IID_IDirect3DResource9,
708 &IID_IUnknown,
709 NULL
710 };
711
712 HRESULT
713 NineSurface9_new( struct NineDevice9 *pDevice,
714 struct NineUnknown *pContainer,
715 struct pipe_resource *pResource,
716 void *user_buffer,
717 uint8_t TextureType,
718 unsigned Level,
719 unsigned Layer,
720 D3DSURFACE_DESC *pDesc,
721 struct NineSurface9 **ppOut )
722 {
723 NINE_DEVICE_CHILD_NEW(Surface9, ppOut, pDevice, /* args */
724 pContainer, pResource, user_buffer,
725 TextureType, Level, Layer, pDesc);
726 }