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