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 "volumetexture9.h"
25bf215546Sopenharmony_ci#include "nine_helpers.h"
26bf215546Sopenharmony_ci#include "nine_pipe.h"
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#define DBG_CHANNEL DBG_VOLUMETEXTURE
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_cistatic HRESULT
31bf215546Sopenharmony_ciNineVolumeTexture9_ctor( struct NineVolumeTexture9 *This,
32bf215546Sopenharmony_ci                         struct NineUnknownParams *pParams,
33bf215546Sopenharmony_ci                         UINT Width, UINT Height, UINT Depth, UINT Levels,
34bf215546Sopenharmony_ci                         DWORD Usage,
35bf215546Sopenharmony_ci                         D3DFORMAT Format,
36bf215546Sopenharmony_ci                         D3DPOOL Pool,
37bf215546Sopenharmony_ci                         HANDLE *pSharedHandle )
38bf215546Sopenharmony_ci{
39bf215546Sopenharmony_ci    struct pipe_resource *info = &This->base.base.info;
40bf215546Sopenharmony_ci    struct pipe_screen *screen = pParams->device->screen;
41bf215546Sopenharmony_ci    enum pipe_format pf;
42bf215546Sopenharmony_ci    unsigned l;
43bf215546Sopenharmony_ci    D3DVOLUME_DESC voldesc;
44bf215546Sopenharmony_ci    HRESULT hr;
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci    DBG("This=%p pParams=%p Width=%u Height=%u Depth=%u Levels=%u "
47bf215546Sopenharmony_ci        "Usage=%d Format=%d Pool=%d pSharedHandle=%p\n",
48bf215546Sopenharmony_ci        This, pParams, Width, Height, Depth, Levels,
49bf215546Sopenharmony_ci        Usage, Format, Pool, pSharedHandle);
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci    user_assert(Width && Height && Depth, D3DERR_INVALIDCALL);
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci    /* user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); */
54bf215546Sopenharmony_ci    user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci    /* An IDirect3DVolume9 cannot be bound as a render target can it ? */
57bf215546Sopenharmony_ci    user_assert(!(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)),
58bf215546Sopenharmony_ci                D3DERR_INVALIDCALL);
59bf215546Sopenharmony_ci    user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP), D3DERR_INVALIDCALL);
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci    pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_3D, 0,
62bf215546Sopenharmony_ci                                     PIPE_BIND_SAMPLER_VIEW, FALSE,
63bf215546Sopenharmony_ci                                     Pool == D3DPOOL_SCRATCH);
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci    if (pf == PIPE_FORMAT_NONE)
66bf215546Sopenharmony_ci        return D3DERR_INVALIDCALL;
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci    /* We support ATI1 and ATI2 hacks only for 2D and Cube textures */
69bf215546Sopenharmony_ci    if (Format == D3DFMT_ATI1 || Format == D3DFMT_ATI2)
70bf215546Sopenharmony_ci        return D3DERR_INVALIDCALL;
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci    if (compressed_format(Format)) {
73bf215546Sopenharmony_ci        const unsigned w = util_format_get_blockwidth(pf);
74bf215546Sopenharmony_ci        const unsigned h = util_format_get_blockheight(pf);
75bf215546Sopenharmony_ci        /* Compressed formats are not compressed on depth component */
76bf215546Sopenharmony_ci        user_assert(!(Width % w) && !(Height % h), D3DERR_INVALIDCALL);
77bf215546Sopenharmony_ci    }
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci    info->screen = pParams->device->screen;
80bf215546Sopenharmony_ci    info->target = PIPE_TEXTURE_3D;
81bf215546Sopenharmony_ci    info->format = pf;
82bf215546Sopenharmony_ci    info->width0 = Width;
83bf215546Sopenharmony_ci    info->height0 = Height;
84bf215546Sopenharmony_ci    info->depth0 = Depth;
85bf215546Sopenharmony_ci    if (Levels)
86bf215546Sopenharmony_ci        info->last_level = Levels - 1;
87bf215546Sopenharmony_ci    else
88bf215546Sopenharmony_ci        info->last_level = util_logbase2(MAX2(MAX2(Width, Height), Depth));
89bf215546Sopenharmony_ci    info->array_size = 1;
90bf215546Sopenharmony_ci    info->nr_samples = 0;
91bf215546Sopenharmony_ci    info->nr_storage_samples = 0;
92bf215546Sopenharmony_ci    info->bind = PIPE_BIND_SAMPLER_VIEW;
93bf215546Sopenharmony_ci    info->usage = PIPE_USAGE_DEFAULT;
94bf215546Sopenharmony_ci    info->flags = 0;
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci    if (Usage & D3DUSAGE_DYNAMIC) {
97bf215546Sopenharmony_ci        info->usage = PIPE_USAGE_DYNAMIC;
98bf215546Sopenharmony_ci    }
99bf215546Sopenharmony_ci    if (Usage & D3DUSAGE_SOFTWAREPROCESSING)
100bf215546Sopenharmony_ci        DBG("Application asked for Software Vertex Processing, "
101bf215546Sopenharmony_ci            "but this is unimplemented\n");
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci    This->base.pstype = 3;
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci    hr = NineBaseTexture9_ctor(&This->base, pParams, NULL,
106bf215546Sopenharmony_ci                               D3DRTYPE_VOLUMETEXTURE, Format, Pool, Usage);
107bf215546Sopenharmony_ci    if (FAILED(hr))
108bf215546Sopenharmony_ci        return hr;
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci    This->volumes = CALLOC(This->base.level_count, sizeof(*This->volumes));
111bf215546Sopenharmony_ci    if (!This->volumes)
112bf215546Sopenharmony_ci        return E_OUTOFMEMORY;
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci    voldesc.Format = Format;
115bf215546Sopenharmony_ci    voldesc.Type = D3DRTYPE_VOLUME;
116bf215546Sopenharmony_ci    voldesc.Usage = Usage;
117bf215546Sopenharmony_ci    voldesc.Pool = Pool;
118bf215546Sopenharmony_ci    for (l = 0; l < This->base.level_count; ++l) {
119bf215546Sopenharmony_ci        voldesc.Width = u_minify(Width, l);
120bf215546Sopenharmony_ci        voldesc.Height = u_minify(Height, l);
121bf215546Sopenharmony_ci        voldesc.Depth = u_minify(Depth, l);
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci        hr = NineVolume9_new(This->base.base.base.device, NineUnknown(This),
124bf215546Sopenharmony_ci                             This->base.base.resource, l,
125bf215546Sopenharmony_ci                             &voldesc, &This->volumes[l]);
126bf215546Sopenharmony_ci        if (FAILED(hr))
127bf215546Sopenharmony_ci            return hr;
128bf215546Sopenharmony_ci    }
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci    /* Textures start initially dirty */
131bf215546Sopenharmony_ci    NineVolumeTexture9_AddDirtyBox(This, NULL);
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci    return D3D_OK;
134bf215546Sopenharmony_ci}
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_cistatic void
137bf215546Sopenharmony_ciNineVolumeTexture9_dtor( struct NineVolumeTexture9 *This )
138bf215546Sopenharmony_ci{
139bf215546Sopenharmony_ci    unsigned l;
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci    DBG("This=%p\n", This);
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci    if (This->volumes) {
144bf215546Sopenharmony_ci        for (l = 0; l < This->base.level_count; ++l)
145bf215546Sopenharmony_ci            if (This->volumes[l])
146bf215546Sopenharmony_ci                NineUnknown_Destroy(&This->volumes[l]->base);
147bf215546Sopenharmony_ci        FREE(This->volumes);
148bf215546Sopenharmony_ci    }
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci    NineBaseTexture9_dtor(&This->base);
151bf215546Sopenharmony_ci}
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ciHRESULT NINE_WINAPI
154bf215546Sopenharmony_ciNineVolumeTexture9_GetLevelDesc( struct NineVolumeTexture9 *This,
155bf215546Sopenharmony_ci                                 UINT Level,
156bf215546Sopenharmony_ci                                 D3DVOLUME_DESC *pDesc )
157bf215546Sopenharmony_ci{
158bf215546Sopenharmony_ci    user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL);
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci    *pDesc = This->volumes[Level]->desc;
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci    return D3D_OK;
163bf215546Sopenharmony_ci}
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ciHRESULT NINE_WINAPI
166bf215546Sopenharmony_ciNineVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This,
167bf215546Sopenharmony_ci                                   UINT Level,
168bf215546Sopenharmony_ci                                   IDirect3DVolume9 **ppVolumeLevel )
169bf215546Sopenharmony_ci{
170bf215546Sopenharmony_ci    user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL);
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci    NineUnknown_AddRef(NineUnknown(This->volumes[Level]));
173bf215546Sopenharmony_ci    *ppVolumeLevel = (IDirect3DVolume9 *)This->volumes[Level];
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci    return D3D_OK;
176bf215546Sopenharmony_ci}
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ciHRESULT NINE_WINAPI
179bf215546Sopenharmony_ciNineVolumeTexture9_LockBox( struct NineVolumeTexture9 *This,
180bf215546Sopenharmony_ci                            UINT Level,
181bf215546Sopenharmony_ci                            D3DLOCKED_BOX *pLockedVolume,
182bf215546Sopenharmony_ci                            const D3DBOX *pBox,
183bf215546Sopenharmony_ci                            DWORD Flags )
184bf215546Sopenharmony_ci{
185bf215546Sopenharmony_ci    DBG("This=%p Level=%u pLockedVolume=%p pBox=%p Flags=%d\n",
186bf215546Sopenharmony_ci        This, Level, pLockedVolume, pBox, Flags);
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci    user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL);
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci    return NineVolume9_LockBox(This->volumes[Level], pLockedVolume, pBox,
191bf215546Sopenharmony_ci                               Flags);
192bf215546Sopenharmony_ci}
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ciHRESULT NINE_WINAPI
195bf215546Sopenharmony_ciNineVolumeTexture9_UnlockBox( struct NineVolumeTexture9 *This,
196bf215546Sopenharmony_ci                              UINT Level )
197bf215546Sopenharmony_ci{
198bf215546Sopenharmony_ci    DBG("This=%p Level=%u\n", This, Level);
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci    user_assert(Level < This->base.level_count, D3DERR_INVALIDCALL);
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci    return NineVolume9_UnlockBox(This->volumes[Level]);
203bf215546Sopenharmony_ci}
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ciHRESULT NINE_WINAPI
206bf215546Sopenharmony_ciNineVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This,
207bf215546Sopenharmony_ci                                const D3DBOX *pDirtyBox )
208bf215546Sopenharmony_ci{
209bf215546Sopenharmony_ci    DBG("This=%p pDirtybox=%p\n", This, pDirtyBox);
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci    if (This->base.base.pool == D3DPOOL_DEFAULT) {
212bf215546Sopenharmony_ci        return D3D_OK;
213bf215546Sopenharmony_ci    }
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci    if (This->base.base.pool == D3DPOOL_MANAGED) {
216bf215546Sopenharmony_ci        This->base.managed.dirty = TRUE;
217bf215546Sopenharmony_ci        BASETEX_REGISTER_UPDATE(&This->base);
218bf215546Sopenharmony_ci    }
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_ci    if (!pDirtyBox) {
221bf215546Sopenharmony_ci        This->dirty_box.x = 0;
222bf215546Sopenharmony_ci        This->dirty_box.y = 0;
223bf215546Sopenharmony_ci        This->dirty_box.z = 0;
224bf215546Sopenharmony_ci        This->dirty_box.width = This->base.base.info.width0;
225bf215546Sopenharmony_ci        This->dirty_box.height = This->base.base.info.height0;
226bf215546Sopenharmony_ci        This->dirty_box.depth = This->base.base.info.depth0;
227bf215546Sopenharmony_ci    } else {
228bf215546Sopenharmony_ci        if (This->dirty_box.width == 0) {
229bf215546Sopenharmony_ci            d3dbox_to_pipe_box(&This->dirty_box, pDirtyBox);
230bf215546Sopenharmony_ci        } else {
231bf215546Sopenharmony_ci            struct pipe_box box;
232bf215546Sopenharmony_ci            d3dbox_to_pipe_box(&box, pDirtyBox);
233bf215546Sopenharmony_ci            u_box_union_3d(&This->dirty_box, &This->dirty_box, &box);
234bf215546Sopenharmony_ci        }
235bf215546Sopenharmony_ci        This->dirty_box.x = MAX2(This->dirty_box.x, 0);
236bf215546Sopenharmony_ci        This->dirty_box.y = MAX2(This->dirty_box.y, 0);
237bf215546Sopenharmony_ci        This->dirty_box.z = MAX2(This->dirty_box.z, 0);
238bf215546Sopenharmony_ci        This->dirty_box.width = MIN2(This->dirty_box.width,
239bf215546Sopenharmony_ci                                     This->base.base.info.width0 - This->dirty_box.x);
240bf215546Sopenharmony_ci        This->dirty_box.height = MIN2(This->dirty_box.height,
241bf215546Sopenharmony_ci                                     This->base.base.info.height0 - This->dirty_box.y);
242bf215546Sopenharmony_ci        This->dirty_box.depth = MIN2(This->dirty_box.depth,
243bf215546Sopenharmony_ci                                     This->base.base.info.depth0 - This->dirty_box.z);
244bf215546Sopenharmony_ci    }
245bf215546Sopenharmony_ci    return D3D_OK;
246bf215546Sopenharmony_ci}
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ciIDirect3DVolumeTexture9Vtbl NineVolumeTexture9_vtable = {
249bf215546Sopenharmony_ci    (void *)NineUnknown_QueryInterface,
250bf215546Sopenharmony_ci    (void *)NineUnknown_AddRef,
251bf215546Sopenharmony_ci    (void *)NineUnknown_Release,
252bf215546Sopenharmony_ci    (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
253bf215546Sopenharmony_ci    (void *)NineUnknown_SetPrivateData,
254bf215546Sopenharmony_ci    (void *)NineUnknown_GetPrivateData,
255bf215546Sopenharmony_ci    (void *)NineUnknown_FreePrivateData,
256bf215546Sopenharmony_ci    (void *)NineResource9_SetPriority,
257bf215546Sopenharmony_ci    (void *)NineResource9_GetPriority,
258bf215546Sopenharmony_ci    (void *)NineBaseTexture9_PreLoad,
259bf215546Sopenharmony_ci    (void *)NineResource9_GetType,
260bf215546Sopenharmony_ci    (void *)NineBaseTexture9_SetLOD,
261bf215546Sopenharmony_ci    (void *)NineBaseTexture9_GetLOD,
262bf215546Sopenharmony_ci    (void *)NineBaseTexture9_GetLevelCount,
263bf215546Sopenharmony_ci    (void *)NineBaseTexture9_SetAutoGenFilterType,
264bf215546Sopenharmony_ci    (void *)NineBaseTexture9_GetAutoGenFilterType,
265bf215546Sopenharmony_ci    (void *)NineBaseTexture9_GenerateMipSubLevels,
266bf215546Sopenharmony_ci    (void *)NineVolumeTexture9_GetLevelDesc,
267bf215546Sopenharmony_ci    (void *)NineVolumeTexture9_GetVolumeLevel,
268bf215546Sopenharmony_ci    (void *)NineVolumeTexture9_LockBox,
269bf215546Sopenharmony_ci    (void *)NineVolumeTexture9_UnlockBox,
270bf215546Sopenharmony_ci    (void *)NineVolumeTexture9_AddDirtyBox
271bf215546Sopenharmony_ci};
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_cistatic const GUID *NineVolumeTexture9_IIDs[] = {
274bf215546Sopenharmony_ci    &IID_IDirect3DVolumeTexture9,
275bf215546Sopenharmony_ci    &IID_IDirect3DBaseTexture9,
276bf215546Sopenharmony_ci    &IID_IDirect3DResource9,
277bf215546Sopenharmony_ci    &IID_IUnknown,
278bf215546Sopenharmony_ci    NULL
279bf215546Sopenharmony_ci};
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ciHRESULT
282bf215546Sopenharmony_ciNineVolumeTexture9_new( struct NineDevice9 *pDevice,
283bf215546Sopenharmony_ci                        UINT Width, UINT Height, UINT Depth, UINT Levels,
284bf215546Sopenharmony_ci                        DWORD Usage,
285bf215546Sopenharmony_ci                        D3DFORMAT Format,
286bf215546Sopenharmony_ci                        D3DPOOL Pool,
287bf215546Sopenharmony_ci                        struct NineVolumeTexture9 **ppOut,
288bf215546Sopenharmony_ci                        HANDLE *pSharedHandle )
289bf215546Sopenharmony_ci{
290bf215546Sopenharmony_ci    NINE_DEVICE_CHILD_NEW(VolumeTexture9, ppOut, pDevice,
291bf215546Sopenharmony_ci                          Width, Height, Depth, Levels,
292bf215546Sopenharmony_ci                          Usage, Format, Pool, pSharedHandle);
293bf215546Sopenharmony_ci}
294bf215546Sopenharmony_ci
295