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