1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#include "device9.h"
24bf215546Sopenharmony_ci#include "volume9.h"
25bf215546Sopenharmony_ci#include "basetexture9.h" /* for marking dirty */
26bf215546Sopenharmony_ci#include "volumetexture9.h"
27bf215546Sopenharmony_ci#include "nine_helpers.h"
28bf215546Sopenharmony_ci#include "nine_pipe.h"
29bf215546Sopenharmony_ci#include "nine_dump.h"
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci#include "util/format/u_format.h"
32bf215546Sopenharmony_ci#include "util/u_surface.h"
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci#define DBG_CHANNEL DBG_VOLUME
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_cistatic HRESULT
38bf215546Sopenharmony_ciNineVolume9_AllocateData( struct NineVolume9 *This )
39bf215546Sopenharmony_ci{
40bf215546Sopenharmony_ci    unsigned size = This->layer_stride * This->desc.Depth;
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci    DBG("(%p(This=%p),level=%u) Allocating 0x%x bytes of system memory.\n",
43bf215546Sopenharmony_ci        This->base.container, This, This->level, size);
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci    This->data = (uint8_t *)align_calloc(size, 32);
46bf215546Sopenharmony_ci    if (!This->data)
47bf215546Sopenharmony_ci        return E_OUTOFMEMORY;
48bf215546Sopenharmony_ci    return D3D_OK;
49bf215546Sopenharmony_ci}
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_cistatic HRESULT
52bf215546Sopenharmony_ciNineVolume9_ctor( struct NineVolume9 *This,
53bf215546Sopenharmony_ci                  struct NineUnknownParams *pParams,
54bf215546Sopenharmony_ci                  struct NineUnknown *pContainer,
55bf215546Sopenharmony_ci                  struct pipe_resource *pResource,
56bf215546Sopenharmony_ci                  unsigned Level,
57bf215546Sopenharmony_ci                  D3DVOLUME_DESC *pDesc )
58bf215546Sopenharmony_ci{
59bf215546Sopenharmony_ci    HRESULT hr;
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci    assert(pContainer); /* stand-alone volumes can't be created */
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci    DBG("This=%p pContainer=%p pDevice=%p pResource=%p Level=%u pDesc=%p\n",
64bf215546Sopenharmony_ci        This, pContainer, pParams->device, pResource, Level, pDesc);
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci    /* Mark this as a special surface held by another internal resource. */
67bf215546Sopenharmony_ci    pParams->container = pContainer;
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci    user_assert(!(pDesc->Usage & D3DUSAGE_DYNAMIC) ||
70bf215546Sopenharmony_ci                (pDesc->Pool != D3DPOOL_MANAGED), D3DERR_INVALIDCALL);
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci    assert(pResource || pDesc->Pool != D3DPOOL_DEFAULT);
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci    hr = NineUnknown_ctor(&This->base, pParams);
75bf215546Sopenharmony_ci    if (FAILED(hr))
76bf215546Sopenharmony_ci        return hr;
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci    pipe_resource_reference(&This->resource, pResource);
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci    This->transfer = NULL;
81bf215546Sopenharmony_ci    This->lock_count = 0;
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci    This->level = Level;
84bf215546Sopenharmony_ci    This->level_actual = Level;
85bf215546Sopenharmony_ci    This->desc = *pDesc;
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci    This->info.screen = pParams->device->screen;
88bf215546Sopenharmony_ci    This->info.target = PIPE_TEXTURE_3D;
89bf215546Sopenharmony_ci    This->info.width0 = pDesc->Width;
90bf215546Sopenharmony_ci    This->info.height0 = pDesc->Height;
91bf215546Sopenharmony_ci    This->info.depth0 = pDesc->Depth;
92bf215546Sopenharmony_ci    This->info.last_level = 0;
93bf215546Sopenharmony_ci    This->info.array_size = 1;
94bf215546Sopenharmony_ci    This->info.nr_samples = 0;
95bf215546Sopenharmony_ci    This->info.nr_storage_samples = 0;
96bf215546Sopenharmony_ci    This->info.usage = PIPE_USAGE_DEFAULT;
97bf215546Sopenharmony_ci    This->info.bind = PIPE_BIND_SAMPLER_VIEW;
98bf215546Sopenharmony_ci    This->info.flags = 0;
99bf215546Sopenharmony_ci    This->info.format = d3d9_to_pipe_format_checked(This->info.screen,
100bf215546Sopenharmony_ci                                                    pDesc->Format,
101bf215546Sopenharmony_ci                                                    This->info.target,
102bf215546Sopenharmony_ci                                                    This->info.nr_samples,
103bf215546Sopenharmony_ci                                                    This->info.bind, FALSE,
104bf215546Sopenharmony_ci                                                    pDesc->Pool == D3DPOOL_SCRATCH);
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci    if (This->info.format == PIPE_FORMAT_NONE)
107bf215546Sopenharmony_ci        return D3DERR_DRIVERINTERNALERROR;
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci    This->stride = util_format_get_stride(This->info.format, pDesc->Width);
110bf215546Sopenharmony_ci    This->stride = align(This->stride, 4);
111bf215546Sopenharmony_ci    This->layer_stride = util_format_get_2d_size(This->info.format,
112bf215546Sopenharmony_ci                                                 This->stride, pDesc->Height);
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci    /* Get true format */
115bf215546Sopenharmony_ci    This->format_internal = d3d9_to_pipe_format_checked(This->info.screen,
116bf215546Sopenharmony_ci                                                         pDesc->Format,
117bf215546Sopenharmony_ci                                                         This->info.target,
118bf215546Sopenharmony_ci                                                         This->info.nr_samples,
119bf215546Sopenharmony_ci                                                         This->info.bind, FALSE,
120bf215546Sopenharmony_ci                                                         TRUE);
121bf215546Sopenharmony_ci    if (This->info.format != This->format_internal ||
122bf215546Sopenharmony_ci        /* See surface9.c */
123bf215546Sopenharmony_ci        (pParams->device->workarounds.dynamic_texture_workaround &&
124bf215546Sopenharmony_ci         pDesc->Pool == D3DPOOL_DEFAULT && pDesc->Usage & D3DUSAGE_DYNAMIC)) {
125bf215546Sopenharmony_ci        This->stride_internal = nine_format_get_stride(This->format_internal,
126bf215546Sopenharmony_ci                                                         pDesc->Width);
127bf215546Sopenharmony_ci        This->layer_stride_internal = util_format_get_2d_size(This->format_internal,
128bf215546Sopenharmony_ci                                                                This->stride_internal,
129bf215546Sopenharmony_ci                                                                pDesc->Height);
130bf215546Sopenharmony_ci        This->data_internal = align_calloc(This->layer_stride_internal *
131bf215546Sopenharmony_ci                                             This->desc.Depth, 32);
132bf215546Sopenharmony_ci        if (!This->data_internal)
133bf215546Sopenharmony_ci            return E_OUTOFMEMORY;
134bf215546Sopenharmony_ci    }
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci    if (!This->resource) {
137bf215546Sopenharmony_ci        hr = NineVolume9_AllocateData(This);
138bf215546Sopenharmony_ci        if (FAILED(hr))
139bf215546Sopenharmony_ci            return hr;
140bf215546Sopenharmony_ci    }
141bf215546Sopenharmony_ci    return D3D_OK;
142bf215546Sopenharmony_ci}
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_cistatic void
145bf215546Sopenharmony_ciNineVolume9_dtor( struct NineVolume9 *This )
146bf215546Sopenharmony_ci{
147bf215546Sopenharmony_ci    DBG("This=%p\n", This);
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci    if (This->transfer) {
150bf215546Sopenharmony_ci        struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.device);
151bf215546Sopenharmony_ci        pipe->texture_unmap(pipe, This->transfer);
152bf215546Sopenharmony_ci        This->transfer = NULL;
153bf215546Sopenharmony_ci    }
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci    /* Note: Following condition cannot happen currently, since we
156bf215546Sopenharmony_ci     * refcount the volume in the functions increasing
157bf215546Sopenharmony_ci     * pending_uploads_counter. */
158bf215546Sopenharmony_ci    if (p_atomic_read(&This->pending_uploads_counter))
159bf215546Sopenharmony_ci        nine_csmt_process(This->base.device);
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci    if (This->data)
162bf215546Sopenharmony_ci        align_free(This->data);
163bf215546Sopenharmony_ci    if (This->data_internal)
164bf215546Sopenharmony_ci        align_free(This->data_internal);
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci    pipe_resource_reference(&This->resource, NULL);
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci    NineUnknown_dtor(&This->base);
169bf215546Sopenharmony_ci}
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ciHRESULT NINE_WINAPI
172bf215546Sopenharmony_ciNineVolume9_GetContainer( struct NineVolume9 *This,
173bf215546Sopenharmony_ci                          REFIID riid,
174bf215546Sopenharmony_ci                          void **ppContainer )
175bf215546Sopenharmony_ci{
176bf215546Sopenharmony_ci    char guid_str[64];
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci    DBG("This=%p riid=%p id=%s ppContainer=%p\n",
179bf215546Sopenharmony_ci        This, riid, riid ? GUID_sprintf(guid_str, riid) : "", ppContainer);
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci    (void)guid_str;
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci    if (!NineUnknown(This)->container)
184bf215546Sopenharmony_ci        return E_NOINTERFACE;
185bf215546Sopenharmony_ci    return NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer);
186bf215546Sopenharmony_ci}
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_cistatic inline void
189bf215546Sopenharmony_ciNineVolume9_MarkContainerDirty( struct NineVolume9 *This )
190bf215546Sopenharmony_ci{
191bf215546Sopenharmony_ci    struct NineBaseTexture9 *tex;
192bf215546Sopenharmony_ci#if defined(DEBUG) || !defined(NDEBUG)
193bf215546Sopenharmony_ci    /* This is always contained by a NineVolumeTexture9. */
194bf215546Sopenharmony_ci    GUID id = IID_IDirect3DVolumeTexture9;
195bf215546Sopenharmony_ci    REFIID ref = &id;
196bf215546Sopenharmony_ci    assert(NineUnknown_QueryInterface(This->base.container, ref, (void **)&tex)
197bf215546Sopenharmony_ci           == S_OK);
198bf215546Sopenharmony_ci    assert(NineUnknown_Release(NineUnknown(tex)) != 0);
199bf215546Sopenharmony_ci#endif
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci    tex = NineBaseTexture9(This->base.container);
202bf215546Sopenharmony_ci    assert(tex);
203bf215546Sopenharmony_ci    if (This->desc.Pool == D3DPOOL_MANAGED)
204bf215546Sopenharmony_ci        tex->managed.dirty = TRUE;
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci    BASETEX_REGISTER_UPDATE(tex);
207bf215546Sopenharmony_ci}
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ciHRESULT NINE_WINAPI
210bf215546Sopenharmony_ciNineVolume9_GetDesc( struct NineVolume9 *This,
211bf215546Sopenharmony_ci                     D3DVOLUME_DESC *pDesc )
212bf215546Sopenharmony_ci{
213bf215546Sopenharmony_ci    user_assert(pDesc != NULL, E_POINTER);
214bf215546Sopenharmony_ci    *pDesc = This->desc;
215bf215546Sopenharmony_ci    return D3D_OK;
216bf215546Sopenharmony_ci}
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ciinline void
219bf215546Sopenharmony_ciNineVolume9_AddDirtyRegion( struct NineVolume9 *This,
220bf215546Sopenharmony_ci                            const struct pipe_box *box )
221bf215546Sopenharmony_ci{
222bf215546Sopenharmony_ci    D3DBOX dirty_region;
223bf215546Sopenharmony_ci    struct NineVolumeTexture9 *tex = NineVolumeTexture9(This->base.container);
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci    if (!box) {
226bf215546Sopenharmony_ci        NineVolumeTexture9_AddDirtyBox(tex, NULL);
227bf215546Sopenharmony_ci    } else {
228bf215546Sopenharmony_ci        dirty_region.Left = box->x << This->level_actual;
229bf215546Sopenharmony_ci        dirty_region.Top = box->y << This->level_actual;
230bf215546Sopenharmony_ci        dirty_region.Front = box->z << This->level_actual;
231bf215546Sopenharmony_ci        dirty_region.Right = dirty_region.Left + (box->width << This->level_actual);
232bf215546Sopenharmony_ci        dirty_region.Bottom = dirty_region.Top + (box->height << This->level_actual);
233bf215546Sopenharmony_ci        dirty_region.Back = dirty_region.Front + (box->depth << This->level_actual);
234bf215546Sopenharmony_ci        NineVolumeTexture9_AddDirtyBox(tex, &dirty_region);
235bf215546Sopenharmony_ci    }
236bf215546Sopenharmony_ci}
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_cistatic inline unsigned
239bf215546Sopenharmony_ciNineVolume9_GetSystemMemOffset(enum pipe_format format, unsigned stride,
240bf215546Sopenharmony_ci                               unsigned layer_stride,
241bf215546Sopenharmony_ci                               int x, int y, int z)
242bf215546Sopenharmony_ci{
243bf215546Sopenharmony_ci    unsigned x_offset = util_format_get_stride(format, x);
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci    y = util_format_get_nblocksy(format, y);
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci    return z * layer_stride + y * stride + x_offset;
248bf215546Sopenharmony_ci}
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ciHRESULT NINE_WINAPI
251bf215546Sopenharmony_ciNineVolume9_LockBox( struct NineVolume9 *This,
252bf215546Sopenharmony_ci                     D3DLOCKED_BOX *pLockedVolume,
253bf215546Sopenharmony_ci                     const D3DBOX *pBox,
254bf215546Sopenharmony_ci                     DWORD Flags )
255bf215546Sopenharmony_ci{
256bf215546Sopenharmony_ci    struct pipe_context *pipe;
257bf215546Sopenharmony_ci    struct pipe_resource *resource = This->resource;
258bf215546Sopenharmony_ci    struct pipe_box box;
259bf215546Sopenharmony_ci    unsigned usage;
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_ci    DBG("This=%p(%p) pLockedVolume=%p pBox=%p[%u..%u,%u..%u,%u..%u] Flags=%s\n",
262bf215546Sopenharmony_ci        This, This->base.container, pLockedVolume, pBox,
263bf215546Sopenharmony_ci        pBox ? pBox->Left : 0, pBox ? pBox->Right : 0,
264bf215546Sopenharmony_ci        pBox ? pBox->Top : 0, pBox ? pBox->Bottom : 0,
265bf215546Sopenharmony_ci        pBox ? pBox->Front : 0, pBox ? pBox->Back : 0,
266bf215546Sopenharmony_ci        nine_D3DLOCK_to_str(Flags));
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci    /* check if it's already locked */
269bf215546Sopenharmony_ci    user_assert(This->lock_count == 0, D3DERR_INVALIDCALL);
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci    /* set pBits to NULL after lock_count check */
272bf215546Sopenharmony_ci    user_assert(pLockedVolume, E_POINTER);
273bf215546Sopenharmony_ci    pLockedVolume->pBits = NULL;
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci    user_assert(This->desc.Pool != D3DPOOL_DEFAULT ||
276bf215546Sopenharmony_ci                (This->desc.Usage & D3DUSAGE_DYNAMIC), D3DERR_INVALIDCALL);
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci    user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)),
279bf215546Sopenharmony_ci                D3DERR_INVALIDCALL);
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci    if (pBox && compressed_format (This->desc.Format)) { /* For volume all pools are checked */
282bf215546Sopenharmony_ci        const unsigned w = util_format_get_blockwidth(This->info.format);
283bf215546Sopenharmony_ci        const unsigned h = util_format_get_blockheight(This->info.format);
284bf215546Sopenharmony_ci        user_assert((pBox->Left == 0 && pBox->Right == This->desc.Width &&
285bf215546Sopenharmony_ci                     pBox->Top == 0 && pBox->Bottom == This->desc.Height) ||
286bf215546Sopenharmony_ci                    (!(pBox->Left % w) && !(pBox->Right % w) &&
287bf215546Sopenharmony_ci                     !(pBox->Top % h) && !(pBox->Bottom % h)),
288bf215546Sopenharmony_ci                    D3DERR_INVALIDCALL);
289bf215546Sopenharmony_ci    }
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci    if (Flags & D3DLOCK_DISCARD) {
292bf215546Sopenharmony_ci        usage = PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE;
293bf215546Sopenharmony_ci    } else {
294bf215546Sopenharmony_ci        usage = (Flags & D3DLOCK_READONLY) ?
295bf215546Sopenharmony_ci            PIPE_MAP_READ : PIPE_MAP_READ_WRITE;
296bf215546Sopenharmony_ci    }
297bf215546Sopenharmony_ci    if (Flags & D3DLOCK_DONOTWAIT)
298bf215546Sopenharmony_ci        usage |= PIPE_MAP_DONTBLOCK;
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_ci    if (pBox) {
301bf215546Sopenharmony_ci        user_assert(pBox->Right > pBox->Left, D3DERR_INVALIDCALL);
302bf215546Sopenharmony_ci        user_assert(pBox->Bottom > pBox->Top, D3DERR_INVALIDCALL);
303bf215546Sopenharmony_ci        user_assert(pBox->Back > pBox->Front, D3DERR_INVALIDCALL);
304bf215546Sopenharmony_ci        user_assert(pBox->Right <= This->desc.Width, D3DERR_INVALIDCALL);
305bf215546Sopenharmony_ci        user_assert(pBox->Bottom <= This->desc.Height, D3DERR_INVALIDCALL);
306bf215546Sopenharmony_ci        user_assert(pBox->Back <= This->desc.Depth, D3DERR_INVALIDCALL);
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci        d3dbox_to_pipe_box(&box, pBox);
309bf215546Sopenharmony_ci        if (u_box_clip_2d(&box, &box, This->desc.Width, This->desc.Height) < 0) {
310bf215546Sopenharmony_ci            DBG("Locked volume intersection empty.\n");
311bf215546Sopenharmony_ci            return D3DERR_INVALIDCALL;
312bf215546Sopenharmony_ci        }
313bf215546Sopenharmony_ci    } else {
314bf215546Sopenharmony_ci        u_box_3d(0, 0, 0, This->desc.Width, This->desc.Height, This->desc.Depth,
315bf215546Sopenharmony_ci                 &box);
316bf215546Sopenharmony_ci    }
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci    if (p_atomic_read(&This->pending_uploads_counter))
319bf215546Sopenharmony_ci        nine_csmt_process(This->base.device);
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci    if (This->data_internal || This->data) {
322bf215546Sopenharmony_ci        enum pipe_format format = This->info.format;
323bf215546Sopenharmony_ci        unsigned stride = This->stride;
324bf215546Sopenharmony_ci        unsigned layer_stride = This->layer_stride;
325bf215546Sopenharmony_ci        uint8_t *data = This->data;
326bf215546Sopenharmony_ci        if (This->data_internal) {
327bf215546Sopenharmony_ci            format = This->format_internal;
328bf215546Sopenharmony_ci            stride = This->stride_internal;
329bf215546Sopenharmony_ci            layer_stride = This->layer_stride_internal;
330bf215546Sopenharmony_ci            data = This->data_internal;
331bf215546Sopenharmony_ci        }
332bf215546Sopenharmony_ci        pLockedVolume->RowPitch = stride;
333bf215546Sopenharmony_ci        pLockedVolume->SlicePitch = layer_stride;
334bf215546Sopenharmony_ci        pLockedVolume->pBits = data +
335bf215546Sopenharmony_ci            NineVolume9_GetSystemMemOffset(format, stride,
336bf215546Sopenharmony_ci                                           layer_stride,
337bf215546Sopenharmony_ci                                           box.x, box.y, box.z);
338bf215546Sopenharmony_ci    } else {
339bf215546Sopenharmony_ci        bool no_refs = !p_atomic_read(&This->base.bind) &&
340bf215546Sopenharmony_ci            !p_atomic_read(&This->base.container->bind);
341bf215546Sopenharmony_ci        if (no_refs)
342bf215546Sopenharmony_ci            pipe = nine_context_get_pipe_acquire(This->base.device);
343bf215546Sopenharmony_ci        else
344bf215546Sopenharmony_ci            pipe = NineDevice9_GetPipe(This->base.device);
345bf215546Sopenharmony_ci        pLockedVolume->pBits =
346bf215546Sopenharmony_ci            pipe->texture_map(pipe, resource, This->level, usage,
347bf215546Sopenharmony_ci                               &box, &This->transfer);
348bf215546Sopenharmony_ci        if (no_refs)
349bf215546Sopenharmony_ci            nine_context_get_pipe_release(This->base.device);
350bf215546Sopenharmony_ci        if (!This->transfer) {
351bf215546Sopenharmony_ci            if (Flags & D3DLOCK_DONOTWAIT)
352bf215546Sopenharmony_ci                return D3DERR_WASSTILLDRAWING;
353bf215546Sopenharmony_ci            return D3DERR_DRIVERINTERNALERROR;
354bf215546Sopenharmony_ci        }
355bf215546Sopenharmony_ci        pLockedVolume->RowPitch = This->transfer->stride;
356bf215546Sopenharmony_ci        pLockedVolume->SlicePitch = This->transfer->layer_stride;
357bf215546Sopenharmony_ci    }
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci    if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) {
360bf215546Sopenharmony_ci        NineVolume9_MarkContainerDirty(This);
361bf215546Sopenharmony_ci        NineVolume9_AddDirtyRegion(This, &box);
362bf215546Sopenharmony_ci    }
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci    ++This->lock_count;
365bf215546Sopenharmony_ci    return D3D_OK;
366bf215546Sopenharmony_ci}
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ciHRESULT NINE_WINAPI
369bf215546Sopenharmony_ciNineVolume9_UnlockBox( struct NineVolume9 *This )
370bf215546Sopenharmony_ci{
371bf215546Sopenharmony_ci    struct pipe_context *pipe;
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci    DBG("This=%p lock_count=%u\n", This, This->lock_count);
374bf215546Sopenharmony_ci    user_assert(This->lock_count, D3DERR_INVALIDCALL);
375bf215546Sopenharmony_ci    if (This->transfer) {
376bf215546Sopenharmony_ci        pipe = nine_context_get_pipe_acquire(This->base.device);
377bf215546Sopenharmony_ci        pipe->texture_unmap(pipe, This->transfer);
378bf215546Sopenharmony_ci        This->transfer = NULL;
379bf215546Sopenharmony_ci        nine_context_get_pipe_release(This->base.device);
380bf215546Sopenharmony_ci    }
381bf215546Sopenharmony_ci    --This->lock_count;
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_ci    if (This->data_internal) {
384bf215546Sopenharmony_ci        struct pipe_box box;
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci        u_box_3d(0, 0, 0, This->desc.Width, This->desc.Height, This->desc.Depth,
387bf215546Sopenharmony_ci                 &box);
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_ci        if (This->data) {
391bf215546Sopenharmony_ci            (void) util_format_translate_3d(This->info.format,
392bf215546Sopenharmony_ci                                            This->data, This->stride,
393bf215546Sopenharmony_ci                                            This->layer_stride,
394bf215546Sopenharmony_ci                                            0, 0, 0,
395bf215546Sopenharmony_ci                                            This->format_internal,
396bf215546Sopenharmony_ci                                            This->data_internal,
397bf215546Sopenharmony_ci                                            This->stride_internal,
398bf215546Sopenharmony_ci                                            This->layer_stride_internal,
399bf215546Sopenharmony_ci                                            0, 0, 0,
400bf215546Sopenharmony_ci                                            This->desc.Width, This->desc.Height,
401bf215546Sopenharmony_ci                                            This->desc.Depth);
402bf215546Sopenharmony_ci        } else {
403bf215546Sopenharmony_ci            nine_context_box_upload(This->base.device,
404bf215546Sopenharmony_ci                                    &This->pending_uploads_counter,
405bf215546Sopenharmony_ci                                    (struct NineUnknown *)This,
406bf215546Sopenharmony_ci                                    This->resource,
407bf215546Sopenharmony_ci                                    This->level,
408bf215546Sopenharmony_ci                                    &box,
409bf215546Sopenharmony_ci                                    This->format_internal,
410bf215546Sopenharmony_ci                                    This->data_internal,
411bf215546Sopenharmony_ci                                    This->stride_internal,
412bf215546Sopenharmony_ci                                    This->layer_stride_internal,
413bf215546Sopenharmony_ci                                    &box);
414bf215546Sopenharmony_ci        }
415bf215546Sopenharmony_ci    }
416bf215546Sopenharmony_ci
417bf215546Sopenharmony_ci    return D3D_OK;
418bf215546Sopenharmony_ci}
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci/* When this function is called, we have already checked
421bf215546Sopenharmony_ci * The copy regions fit the volumes */
422bf215546Sopenharmony_civoid
423bf215546Sopenharmony_ciNineVolume9_CopyMemToDefault( struct NineVolume9 *This,
424bf215546Sopenharmony_ci                              struct NineVolume9 *From,
425bf215546Sopenharmony_ci                              unsigned dstx, unsigned dsty, unsigned dstz,
426bf215546Sopenharmony_ci                              struct pipe_box *pSrcBox )
427bf215546Sopenharmony_ci{
428bf215546Sopenharmony_ci    struct pipe_resource *r_dst = This->resource;
429bf215546Sopenharmony_ci    struct pipe_box src_box;
430bf215546Sopenharmony_ci    struct pipe_box dst_box;
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci    DBG("This=%p From=%p dstx=%u dsty=%u dstz=%u pSrcBox=%p\n",
433bf215546Sopenharmony_ci        This, From, dstx, dsty, dstz, pSrcBox);
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_ci    assert(This->desc.Pool == D3DPOOL_DEFAULT &&
436bf215546Sopenharmony_ci           From->desc.Pool == D3DPOOL_SYSTEMMEM);
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_ci    dst_box.x = dstx;
439bf215546Sopenharmony_ci    dst_box.y = dsty;
440bf215546Sopenharmony_ci    dst_box.z = dstz;
441bf215546Sopenharmony_ci
442bf215546Sopenharmony_ci    if (pSrcBox) {
443bf215546Sopenharmony_ci        src_box = *pSrcBox;
444bf215546Sopenharmony_ci    } else {
445bf215546Sopenharmony_ci        src_box.x = 0;
446bf215546Sopenharmony_ci        src_box.y = 0;
447bf215546Sopenharmony_ci        src_box.z = 0;
448bf215546Sopenharmony_ci        src_box.width = From->desc.Width;
449bf215546Sopenharmony_ci        src_box.height = From->desc.Height;
450bf215546Sopenharmony_ci        src_box.depth = From->desc.Depth;
451bf215546Sopenharmony_ci    }
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_ci    dst_box.width = src_box.width;
454bf215546Sopenharmony_ci    dst_box.height = src_box.height;
455bf215546Sopenharmony_ci    dst_box.depth = src_box.depth;
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci    nine_context_box_upload(This->base.device,
458bf215546Sopenharmony_ci                            &From->pending_uploads_counter,
459bf215546Sopenharmony_ci                            (struct NineUnknown *)From,
460bf215546Sopenharmony_ci                            r_dst,
461bf215546Sopenharmony_ci                            This->level,
462bf215546Sopenharmony_ci                            &dst_box,
463bf215546Sopenharmony_ci                            From->info.format,
464bf215546Sopenharmony_ci                            From->data, From->stride,
465bf215546Sopenharmony_ci                            From->layer_stride,
466bf215546Sopenharmony_ci                            &src_box);
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_ci    if (This->data_internal)
469bf215546Sopenharmony_ci        (void) util_format_translate_3d(This->format_internal,
470bf215546Sopenharmony_ci                                        This->data_internal,
471bf215546Sopenharmony_ci                                        This->stride_internal,
472bf215546Sopenharmony_ci                                        This->layer_stride_internal,
473bf215546Sopenharmony_ci                                        dstx, dsty, dstz,
474bf215546Sopenharmony_ci                                        From->info.format,
475bf215546Sopenharmony_ci                                        From->data, From->stride,
476bf215546Sopenharmony_ci                                        From->layer_stride,
477bf215546Sopenharmony_ci                                        src_box.x, src_box.y,
478bf215546Sopenharmony_ci                                        src_box.z,
479bf215546Sopenharmony_ci                                        src_box.width,
480bf215546Sopenharmony_ci                                        src_box.height,
481bf215546Sopenharmony_ci                                        src_box.depth);
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci    NineVolume9_MarkContainerDirty(This);
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ci    return;
486bf215546Sopenharmony_ci}
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ciHRESULT
489bf215546Sopenharmony_ciNineVolume9_UploadSelf( struct NineVolume9 *This,
490bf215546Sopenharmony_ci                        const struct pipe_box *damaged )
491bf215546Sopenharmony_ci{
492bf215546Sopenharmony_ci    struct pipe_resource *res = This->resource;
493bf215546Sopenharmony_ci    struct pipe_box box;
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_ci    DBG("This=%p damaged=%p data=%p res=%p\n", This, damaged,
496bf215546Sopenharmony_ci        This->data, res);
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci    assert(This->desc.Pool == D3DPOOL_MANAGED);
499bf215546Sopenharmony_ci    assert(res);
500bf215546Sopenharmony_ci
501bf215546Sopenharmony_ci    if (damaged) {
502bf215546Sopenharmony_ci        box = *damaged;
503bf215546Sopenharmony_ci    } else {
504bf215546Sopenharmony_ci        box.x = 0;
505bf215546Sopenharmony_ci        box.y = 0;
506bf215546Sopenharmony_ci        box.z = 0;
507bf215546Sopenharmony_ci        box.width = This->desc.Width;
508bf215546Sopenharmony_ci        box.height = This->desc.Height;
509bf215546Sopenharmony_ci        box.depth = This->desc.Depth;
510bf215546Sopenharmony_ci    }
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_ci    nine_context_box_upload(This->base.device,
513bf215546Sopenharmony_ci                            &This->pending_uploads_counter,
514bf215546Sopenharmony_ci                            (struct NineUnknown *)This,
515bf215546Sopenharmony_ci                            res,
516bf215546Sopenharmony_ci                            This->level,
517bf215546Sopenharmony_ci                            &box,
518bf215546Sopenharmony_ci                            res->format,
519bf215546Sopenharmony_ci                            This->data, This->stride,
520bf215546Sopenharmony_ci                            This->layer_stride,
521bf215546Sopenharmony_ci                            &box);
522bf215546Sopenharmony_ci
523bf215546Sopenharmony_ci    return D3D_OK;
524bf215546Sopenharmony_ci}
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_ciIDirect3DVolume9Vtbl NineVolume9_vtable = {
528bf215546Sopenharmony_ci    (void *)NineUnknown_QueryInterface,
529bf215546Sopenharmony_ci    (void *)NineUnknown_AddRef,
530bf215546Sopenharmony_ci    (void *)NineUnknown_Release,
531bf215546Sopenharmony_ci    (void *)NineUnknown_GetDevice, /* actually part of Volume9 iface */
532bf215546Sopenharmony_ci    (void *)NineUnknown_SetPrivateData,
533bf215546Sopenharmony_ci    (void *)NineUnknown_GetPrivateData,
534bf215546Sopenharmony_ci    (void *)NineUnknown_FreePrivateData,
535bf215546Sopenharmony_ci    (void *)NineVolume9_GetContainer,
536bf215546Sopenharmony_ci    (void *)NineVolume9_GetDesc,
537bf215546Sopenharmony_ci    (void *)NineVolume9_LockBox,
538bf215546Sopenharmony_ci    (void *)NineVolume9_UnlockBox
539bf215546Sopenharmony_ci};
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_cistatic const GUID *NineVolume9_IIDs[] = {
542bf215546Sopenharmony_ci    &IID_IDirect3DVolume9,
543bf215546Sopenharmony_ci    &IID_IUnknown,
544bf215546Sopenharmony_ci    NULL
545bf215546Sopenharmony_ci};
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_ciHRESULT
548bf215546Sopenharmony_ciNineVolume9_new( struct NineDevice9 *pDevice,
549bf215546Sopenharmony_ci                 struct NineUnknown *pContainer,
550bf215546Sopenharmony_ci                 struct pipe_resource *pResource,
551bf215546Sopenharmony_ci                 unsigned Level,
552bf215546Sopenharmony_ci                 D3DVOLUME_DESC *pDesc,
553bf215546Sopenharmony_ci                 struct NineVolume9 **ppOut )
554bf215546Sopenharmony_ci{
555bf215546Sopenharmony_ci    NINE_DEVICE_CHILD_NEW(Volume9, ppOut, pDevice, /* args */
556bf215546Sopenharmony_ci                          pContainer, pResource, Level, pDesc);
557bf215546Sopenharmony_ci}
558