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 "basetexture9.h"
24bf215546Sopenharmony_ci#include "device9.h"
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci/* For UploadSelf: */
27bf215546Sopenharmony_ci#include "texture9.h"
28bf215546Sopenharmony_ci#include "cubetexture9.h"
29bf215546Sopenharmony_ci#include "volumetexture9.h"
30bf215546Sopenharmony_ci#include "nine_pipe.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#if defined(DEBUG) || !defined(NDEBUG)
33bf215546Sopenharmony_ci#include "nine_dump.h"
34bf215546Sopenharmony_ci#endif
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci#include "util/format/u_format.h"
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#define DBG_CHANNEL DBG_BASETEXTURE
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ciHRESULT
41bf215546Sopenharmony_ciNineBaseTexture9_ctor( struct NineBaseTexture9 *This,
42bf215546Sopenharmony_ci                       struct NineUnknownParams *pParams,
43bf215546Sopenharmony_ci                       struct pipe_resource *initResource,
44bf215546Sopenharmony_ci                       D3DRESOURCETYPE Type,
45bf215546Sopenharmony_ci                       D3DFORMAT format,
46bf215546Sopenharmony_ci                       D3DPOOL Pool,
47bf215546Sopenharmony_ci                       DWORD Usage)
48bf215546Sopenharmony_ci{
49bf215546Sopenharmony_ci    BOOL alloc = (Pool == D3DPOOL_DEFAULT) && !initResource &&
50bf215546Sopenharmony_ci        (format != D3DFMT_NULL);
51bf215546Sopenharmony_ci    HRESULT hr;
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci    DBG("This=%p, pParams=%p initResource=%p Type=%d format=%d Pool=%d Usage=%d\n",
54bf215546Sopenharmony_ci        This, pParams, initResource, Type, format, Pool, Usage);
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci    user_assert(!(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) ||
57bf215546Sopenharmony_ci                Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
58bf215546Sopenharmony_ci    user_assert(!(Usage & D3DUSAGE_DYNAMIC) ||
59bf215546Sopenharmony_ci                !(Pool == D3DPOOL_MANAGED ||
60bf215546Sopenharmony_ci                  Pool == D3DPOOL_SCRATCH), D3DERR_INVALIDCALL);
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci    hr = NineResource9_ctor(&This->base, pParams, initResource, alloc, Type, Pool, Usage);
63bf215546Sopenharmony_ci    if (FAILED(hr))
64bf215546Sopenharmony_ci        return hr;
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci    This->format = format;
67bf215546Sopenharmony_ci    This->mipfilter = (Usage & D3DUSAGE_AUTOGENMIPMAP) ?
68bf215546Sopenharmony_ci        D3DTEXF_LINEAR : D3DTEXF_NONE;
69bf215546Sopenharmony_ci    /* In the case of D3DUSAGE_AUTOGENMIPMAP, only the first level is accessible,
70bf215546Sopenharmony_ci     * and thus needs a surface created. */
71bf215546Sopenharmony_ci    This->level_count = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? 1 : (This->base.info.last_level+1);
72bf215546Sopenharmony_ci    This->managed.lod = 0;
73bf215546Sopenharmony_ci    This->managed.lod_resident = -1;
74bf215546Sopenharmony_ci    /* Mark the texture as dirty to trigger first upload when we need the texture,
75bf215546Sopenharmony_ci     * even if it wasn't set by the application */
76bf215546Sopenharmony_ci    if (Pool == D3DPOOL_MANAGED)
77bf215546Sopenharmony_ci        This->managed.dirty = TRUE;
78bf215546Sopenharmony_ci    /* When a depth buffer is sampled, it is for shadow mapping, except for
79bf215546Sopenharmony_ci     * D3DFMT_INTZ, D3DFMT_DF16 and D3DFMT_DF24.
80bf215546Sopenharmony_ci     * In addition D3DFMT_INTZ can be used for both texturing and depth buffering
81bf215546Sopenharmony_ci     * if z write is disabled. This particular feature may not work for us in
82bf215546Sopenharmony_ci     * practice because OGL doesn't have that. However apparently it is known
83bf215546Sopenharmony_ci     * some cards have performance issues with this feature, so real apps
84bf215546Sopenharmony_ci     * shouldn't use it. */
85bf215546Sopenharmony_ci    This->shadow = (This->format != D3DFMT_INTZ && This->format != D3DFMT_DF16 &&
86bf215546Sopenharmony_ci                    This->format != D3DFMT_DF24) &&
87bf215546Sopenharmony_ci                   util_format_has_depth(util_format_description(This->base.info.format));
88bf215546Sopenharmony_ci    This->fetch4_compatible = fetch4_compatible_format(This->format);
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci    list_inithead(&This->list);
91bf215546Sopenharmony_ci    list_inithead(&This->list2);
92bf215546Sopenharmony_ci    if (Pool == D3DPOOL_MANAGED)
93bf215546Sopenharmony_ci        list_add(&This->list2, &This->base.base.device->managed_textures);
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci    return D3D_OK;
96bf215546Sopenharmony_ci}
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_civoid
99bf215546Sopenharmony_ciNineBaseTexture9_dtor( struct NineBaseTexture9 *This )
100bf215546Sopenharmony_ci{
101bf215546Sopenharmony_ci    DBG("This=%p\n", This);
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci    pipe_sampler_view_reference(&This->view[0], NULL);
104bf215546Sopenharmony_ci    pipe_sampler_view_reference(&This->view[1], NULL);
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci    if (list_is_linked(&This->list))
107bf215546Sopenharmony_ci        list_del(&This->list);
108bf215546Sopenharmony_ci    if (list_is_linked(&This->list2))
109bf215546Sopenharmony_ci        list_del(&This->list2);
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci    NineResource9_dtor(&This->base);
112bf215546Sopenharmony_ci}
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ciDWORD NINE_WINAPI
115bf215546Sopenharmony_ciNineBaseTexture9_SetLOD( struct NineBaseTexture9 *This,
116bf215546Sopenharmony_ci                         DWORD LODNew )
117bf215546Sopenharmony_ci{
118bf215546Sopenharmony_ci    DWORD old = This->managed.lod;
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci    DBG("This=%p LODNew=%d\n", This, LODNew);
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci    user_assert(This->base.pool == D3DPOOL_MANAGED, 0);
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci    This->managed.lod = MIN2(LODNew, This->level_count-1);
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci    if (This->managed.lod != old && This->bind_count && list_is_empty(&This->list))
127bf215546Sopenharmony_ci       list_add(&This->list, &This->base.base.device->update_textures);
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci    return old;
130bf215546Sopenharmony_ci}
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ciDWORD NINE_WINAPI
133bf215546Sopenharmony_ciNineBaseTexture9_GetLOD( struct NineBaseTexture9 *This )
134bf215546Sopenharmony_ci{
135bf215546Sopenharmony_ci    DBG("This=%p\n", This);
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci    return This->managed.lod;
138bf215546Sopenharmony_ci}
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ciDWORD NINE_WINAPI
141bf215546Sopenharmony_ciNineBaseTexture9_GetLevelCount( struct NineBaseTexture9 *This )
142bf215546Sopenharmony_ci{
143bf215546Sopenharmony_ci    DBG("This=%p\n", This);
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci    return This->level_count;
146bf215546Sopenharmony_ci}
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ciHRESULT NINE_WINAPI
149bf215546Sopenharmony_ciNineBaseTexture9_SetAutoGenFilterType( struct NineBaseTexture9 *This,
150bf215546Sopenharmony_ci                                       D3DTEXTUREFILTERTYPE FilterType )
151bf215546Sopenharmony_ci{
152bf215546Sopenharmony_ci    DBG("This=%p FilterType=%d\n", This, FilterType);
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci    if (!(This->base.usage & D3DUSAGE_AUTOGENMIPMAP))
155bf215546Sopenharmony_ci        return D3D_OK;
156bf215546Sopenharmony_ci    user_assert(FilterType != D3DTEXF_NONE, D3DERR_INVALIDCALL);
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci    This->mipfilter = FilterType;
159bf215546Sopenharmony_ci    This->dirty_mip = TRUE;
160bf215546Sopenharmony_ci    NineBaseTexture9_GenerateMipSubLevels(This);
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci    return D3D_OK;
163bf215546Sopenharmony_ci}
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ciD3DTEXTUREFILTERTYPE NINE_WINAPI
166bf215546Sopenharmony_ciNineBaseTexture9_GetAutoGenFilterType( struct NineBaseTexture9 *This )
167bf215546Sopenharmony_ci{
168bf215546Sopenharmony_ci    DBG("This=%p\n", This);
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci    return This->mipfilter;
171bf215546Sopenharmony_ci}
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ciHRESULT
174bf215546Sopenharmony_ciNineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This )
175bf215546Sopenharmony_ci{
176bf215546Sopenharmony_ci    HRESULT hr;
177bf215546Sopenharmony_ci    unsigned l, min_level_dirty = This->managed.lod;
178bf215546Sopenharmony_ci    BOOL update_lod;
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci    DBG("This=%p dirty=%i type=%s\n", This, This->managed.dirty,
181bf215546Sopenharmony_ci        nine_D3DRTYPE_to_str(This->base.type));
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci    assert(This->base.pool == D3DPOOL_MANAGED);
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci    update_lod = This->managed.lod_resident != This->managed.lod;
186bf215546Sopenharmony_ci    if (!update_lod && !This->managed.dirty)
187bf215546Sopenharmony_ci        return D3D_OK;
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci    /* Allocate a new resource with the correct number of levels,
190bf215546Sopenharmony_ci     * Mark states for update, and tell the nine surfaces/volumes
191bf215546Sopenharmony_ci     * their new resource. */
192bf215546Sopenharmony_ci    if (update_lod) {
193bf215546Sopenharmony_ci        struct pipe_resource *res;
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci        DBG("updating LOD from %u to %u ...\n", This->managed.lod_resident, This->managed.lod);
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci        pipe_sampler_view_reference(&This->view[0], NULL);
198bf215546Sopenharmony_ci        pipe_sampler_view_reference(&This->view[1], NULL);
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci        /* Allocate a new resource */
201bf215546Sopenharmony_ci        hr = NineBaseTexture9_CreatePipeResource(This, This->managed.lod_resident != -1);
202bf215546Sopenharmony_ci        if (FAILED(hr))
203bf215546Sopenharmony_ci            return hr;
204bf215546Sopenharmony_ci        res = This->base.resource;
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci        if (This->managed.lod_resident == -1) {/* no levels were resident */
207bf215546Sopenharmony_ci            This->managed.dirty = FALSE; /* We are going to upload everything. */
208bf215546Sopenharmony_ci            This->managed.lod_resident = This->level_count;
209bf215546Sopenharmony_ci        }
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci        if (This->base.type == D3DRTYPE_TEXTURE) {
212bf215546Sopenharmony_ci            struct NineTexture9 *tex = NineTexture9(This);
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci            /* last content (if apply) has been copied to the new resource.
215bf215546Sopenharmony_ci             * Note: We cannot render to surfaces of managed textures.
216bf215546Sopenharmony_ci             * Note2: the level argument passed is to get the level offset
217bf215546Sopenharmony_ci             * right when the texture is uploaded (the texture first level
218bf215546Sopenharmony_ci             * corresponds to This->managed.lod).
219bf215546Sopenharmony_ci             * Note3: We don't care about the value passed for the surfaces
220bf215546Sopenharmony_ci             * before This->managed.lod, negative with this implementation. */
221bf215546Sopenharmony_ci            for (l = 0; l < This->level_count; ++l)
222bf215546Sopenharmony_ci                NineSurface9_SetResource(tex->surfaces[l], res, l - This->managed.lod);
223bf215546Sopenharmony_ci        } else
224bf215546Sopenharmony_ci        if (This->base.type == D3DRTYPE_CUBETEXTURE) {
225bf215546Sopenharmony_ci            struct NineCubeTexture9 *tex = NineCubeTexture9(This);
226bf215546Sopenharmony_ci            unsigned z;
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci            for (l = 0; l < This->level_count; ++l) {
229bf215546Sopenharmony_ci                for (z = 0; z < 6; ++z)
230bf215546Sopenharmony_ci                    NineSurface9_SetResource(tex->surfaces[l * 6 + z],
231bf215546Sopenharmony_ci                                             res, l - This->managed.lod);
232bf215546Sopenharmony_ci            }
233bf215546Sopenharmony_ci        } else
234bf215546Sopenharmony_ci        if (This->base.type == D3DRTYPE_VOLUMETEXTURE) {
235bf215546Sopenharmony_ci            struct NineVolumeTexture9 *tex = NineVolumeTexture9(This);
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci            for (l = 0; l < This->level_count; ++l)
238bf215546Sopenharmony_ci                NineVolume9_SetResource(tex->volumes[l], res, l - This->managed.lod);
239bf215546Sopenharmony_ci        } else {
240bf215546Sopenharmony_ci            assert(!"invalid texture type");
241bf215546Sopenharmony_ci        }
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci        /* We are going to fully upload the new levels,
244bf215546Sopenharmony_ci         * no need to update dirty parts of the texture for these */
245bf215546Sopenharmony_ci        min_level_dirty = MAX2(This->managed.lod, This->managed.lod_resident);
246bf215546Sopenharmony_ci    }
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci    /* Update dirty parts of the texture */
249bf215546Sopenharmony_ci    if (This->managed.dirty) {
250bf215546Sopenharmony_ci        if (This->base.type == D3DRTYPE_TEXTURE) {
251bf215546Sopenharmony_ci            struct NineTexture9 *tex = NineTexture9(This);
252bf215546Sopenharmony_ci            struct pipe_box box;
253bf215546Sopenharmony_ci            box.z = 0;
254bf215546Sopenharmony_ci            box.depth = 1;
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci            DBG("TEXTURE: dirty rect=(%u,%u) (%ux%u)\n",
257bf215546Sopenharmony_ci                tex->dirty_rect.x, tex->dirty_rect.y,
258bf215546Sopenharmony_ci                tex->dirty_rect.width, tex->dirty_rect.height);
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci            /* Note: for l < min_level_dirty, the resource is
261bf215546Sopenharmony_ci             * either non-existing (and thus will be entirely re-uploaded
262bf215546Sopenharmony_ci             * if the lod changes) or going to have a full upload */
263bf215546Sopenharmony_ci            if (tex->dirty_rect.width) {
264bf215546Sopenharmony_ci                for (l = min_level_dirty; l < This->level_count; ++l) {
265bf215546Sopenharmony_ci                    u_box_minify_2d(&box, &tex->dirty_rect, l);
266bf215546Sopenharmony_ci                    NineSurface9_UploadSelf(tex->surfaces[l], &box);
267bf215546Sopenharmony_ci                }
268bf215546Sopenharmony_ci                memset(&tex->dirty_rect, 0, sizeof(tex->dirty_rect));
269bf215546Sopenharmony_ci                tex->dirty_rect.depth = 1;
270bf215546Sopenharmony_ci            }
271bf215546Sopenharmony_ci        } else
272bf215546Sopenharmony_ci        if (This->base.type == D3DRTYPE_CUBETEXTURE) {
273bf215546Sopenharmony_ci            struct NineCubeTexture9 *tex = NineCubeTexture9(This);
274bf215546Sopenharmony_ci            unsigned z;
275bf215546Sopenharmony_ci            struct pipe_box box;
276bf215546Sopenharmony_ci            box.z = 0;
277bf215546Sopenharmony_ci            box.depth = 1;
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci            for (z = 0; z < 6; ++z) {
280bf215546Sopenharmony_ci                DBG("FACE[%u]: dirty rect=(%u,%u) (%ux%u)\n", z,
281bf215546Sopenharmony_ci                    tex->dirty_rect[z].x, tex->dirty_rect[z].y,
282bf215546Sopenharmony_ci                    tex->dirty_rect[z].width, tex->dirty_rect[z].height);
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci                if (tex->dirty_rect[z].width) {
285bf215546Sopenharmony_ci                    for (l = min_level_dirty; l < This->level_count; ++l) {
286bf215546Sopenharmony_ci                        u_box_minify_2d(&box, &tex->dirty_rect[z], l);
287bf215546Sopenharmony_ci                        NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box);
288bf215546Sopenharmony_ci                    }
289bf215546Sopenharmony_ci                    memset(&tex->dirty_rect[z], 0, sizeof(tex->dirty_rect[z]));
290bf215546Sopenharmony_ci                    tex->dirty_rect[z].depth = 1;
291bf215546Sopenharmony_ci                }
292bf215546Sopenharmony_ci            }
293bf215546Sopenharmony_ci        } else
294bf215546Sopenharmony_ci        if (This->base.type == D3DRTYPE_VOLUMETEXTURE) {
295bf215546Sopenharmony_ci            struct NineVolumeTexture9 *tex = NineVolumeTexture9(This);
296bf215546Sopenharmony_ci            struct pipe_box box;
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci            DBG("VOLUME: dirty_box=(%u,%u,%u) (%ux%ux%u)\n",
299bf215546Sopenharmony_ci                tex->dirty_box.x, tex->dirty_box.y, tex->dirty_box.y,
300bf215546Sopenharmony_ci                tex->dirty_box.width, tex->dirty_box.height, tex->dirty_box.depth);
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci            if (tex->dirty_box.width) {
303bf215546Sopenharmony_ci                for (l = min_level_dirty; l < This->level_count; ++l) {
304bf215546Sopenharmony_ci                    u_box_minify_3d(&box, &tex->dirty_box, l);
305bf215546Sopenharmony_ci                    NineVolume9_UploadSelf(tex->volumes[l], &box);
306bf215546Sopenharmony_ci                }
307bf215546Sopenharmony_ci                memset(&tex->dirty_box, 0, sizeof(tex->dirty_box));
308bf215546Sopenharmony_ci            }
309bf215546Sopenharmony_ci        } else {
310bf215546Sopenharmony_ci            assert(!"invalid texture type");
311bf215546Sopenharmony_ci        }
312bf215546Sopenharmony_ci        This->managed.dirty = FALSE;
313bf215546Sopenharmony_ci    }
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci    /* Upload the new levels */
316bf215546Sopenharmony_ci    if (update_lod) {
317bf215546Sopenharmony_ci        if (This->base.type == D3DRTYPE_TEXTURE) {
318bf215546Sopenharmony_ci            struct NineTexture9 *tex = NineTexture9(This);
319bf215546Sopenharmony_ci            struct pipe_box box;
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci            box.x = box.y = box.z = 0;
322bf215546Sopenharmony_ci            box.depth = 1;
323bf215546Sopenharmony_ci            for (l = This->managed.lod; l < This->managed.lod_resident; ++l) {
324bf215546Sopenharmony_ci                box.width = u_minify(This->base.info.width0, l);
325bf215546Sopenharmony_ci                box.height = u_minify(This->base.info.height0, l);
326bf215546Sopenharmony_ci                NineSurface9_UploadSelf(tex->surfaces[l], &box);
327bf215546Sopenharmony_ci            }
328bf215546Sopenharmony_ci        } else
329bf215546Sopenharmony_ci        if (This->base.type == D3DRTYPE_CUBETEXTURE) {
330bf215546Sopenharmony_ci            struct NineCubeTexture9 *tex = NineCubeTexture9(This);
331bf215546Sopenharmony_ci            struct pipe_box box;
332bf215546Sopenharmony_ci            unsigned z;
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci            box.x = box.y = box.z = 0;
335bf215546Sopenharmony_ci            box.depth = 1;
336bf215546Sopenharmony_ci            for (l = This->managed.lod; l < This->managed.lod_resident; ++l) {
337bf215546Sopenharmony_ci                box.width = u_minify(This->base.info.width0, l);
338bf215546Sopenharmony_ci                box.height = u_minify(This->base.info.height0, l);
339bf215546Sopenharmony_ci                for (z = 0; z < 6; ++z)
340bf215546Sopenharmony_ci                    NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box);
341bf215546Sopenharmony_ci            }
342bf215546Sopenharmony_ci        } else
343bf215546Sopenharmony_ci        if (This->base.type == D3DRTYPE_VOLUMETEXTURE) {
344bf215546Sopenharmony_ci            struct NineVolumeTexture9 *tex = NineVolumeTexture9(This);
345bf215546Sopenharmony_ci            struct pipe_box box;
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci            box.x = box.y = box.z = 0;
348bf215546Sopenharmony_ci            for (l = This->managed.lod; l < This->managed.lod_resident; ++l) {
349bf215546Sopenharmony_ci                box.width = u_minify(This->base.info.width0, l);
350bf215546Sopenharmony_ci                box.height = u_minify(This->base.info.height0, l);
351bf215546Sopenharmony_ci                box.depth = u_minify(This->base.info.depth0, l);
352bf215546Sopenharmony_ci                NineVolume9_UploadSelf(tex->volumes[l], &box);
353bf215546Sopenharmony_ci            }
354bf215546Sopenharmony_ci        } else {
355bf215546Sopenharmony_ci            assert(!"invalid texture type");
356bf215546Sopenharmony_ci        }
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci        This->managed.lod_resident = This->managed.lod;
359bf215546Sopenharmony_ci    }
360bf215546Sopenharmony_ci
361bf215546Sopenharmony_ci    if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP)
362bf215546Sopenharmony_ci        This->dirty_mip = TRUE;
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci    /* Set again the textures currently bound to update the texture data */
365bf215546Sopenharmony_ci    if (This->bind_count) {
366bf215546Sopenharmony_ci        struct nine_state *state = &This->base.base.device->state;
367bf215546Sopenharmony_ci        unsigned s;
368bf215546Sopenharmony_ci        for (s = 0; s < NINE_MAX_SAMPLERS; ++s)
369bf215546Sopenharmony_ci            /* Dirty tracking is done in device9 state, not nine_context. */
370bf215546Sopenharmony_ci            if (state->texture[s] == This)
371bf215546Sopenharmony_ci                nine_context_set_texture(This->base.base.device, s, This);
372bf215546Sopenharmony_ci    }
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci    DBG("DONE, generate mip maps = %i\n", This->dirty_mip);
375bf215546Sopenharmony_ci    return D3D_OK;
376bf215546Sopenharmony_ci}
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_civoid NINE_WINAPI
379bf215546Sopenharmony_ciNineBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This )
380bf215546Sopenharmony_ci{
381bf215546Sopenharmony_ci    unsigned base_level = 0;
382bf215546Sopenharmony_ci    unsigned last_level = This->base.info.last_level - This->managed.lod;
383bf215546Sopenharmony_ci    unsigned first_layer = 0;
384bf215546Sopenharmony_ci    unsigned last_layer;
385bf215546Sopenharmony_ci    unsigned filter = This->mipfilter == D3DTEXF_POINT ? PIPE_TEX_FILTER_NEAREST
386bf215546Sopenharmony_ci                                                       : PIPE_TEX_FILTER_LINEAR;
387bf215546Sopenharmony_ci    DBG("This=%p\n", This);
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci    if (This->base.pool == D3DPOOL_MANAGED)
390bf215546Sopenharmony_ci        NineBaseTexture9_UploadSelf(This);
391bf215546Sopenharmony_ci    if (!This->dirty_mip)
392bf215546Sopenharmony_ci        return;
393bf215546Sopenharmony_ci    if (This->managed.lod) {
394bf215546Sopenharmony_ci        ERR("AUTOGENMIPMAP if level 0 is not resident not supported yet !\n");
395bf215546Sopenharmony_ci        return;
396bf215546Sopenharmony_ci    }
397bf215546Sopenharmony_ci
398bf215546Sopenharmony_ci    if (!This->view[0])
399bf215546Sopenharmony_ci        NineBaseTexture9_UpdateSamplerView(This, 0);
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci    last_layer = util_max_layer(This->view[0]->texture, base_level);
402bf215546Sopenharmony_ci
403bf215546Sopenharmony_ci    nine_context_gen_mipmap(This->base.base.device, (struct NineUnknown *)This,
404bf215546Sopenharmony_ci                            This->base.resource,
405bf215546Sopenharmony_ci                            base_level, last_level,
406bf215546Sopenharmony_ci                            first_layer, last_layer, filter);
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_ci    This->dirty_mip = FALSE;
409bf215546Sopenharmony_ci}
410bf215546Sopenharmony_ci
411bf215546Sopenharmony_ciHRESULT
412bf215546Sopenharmony_ciNineBaseTexture9_CreatePipeResource( struct NineBaseTexture9 *This,
413bf215546Sopenharmony_ci                                     BOOL CopyData )
414bf215546Sopenharmony_ci{
415bf215546Sopenharmony_ci    struct pipe_context *pipe;
416bf215546Sopenharmony_ci    struct pipe_screen *screen = This->base.info.screen;
417bf215546Sopenharmony_ci    struct pipe_resource templ;
418bf215546Sopenharmony_ci    unsigned l, m;
419bf215546Sopenharmony_ci    struct pipe_resource *res;
420bf215546Sopenharmony_ci    struct pipe_resource *old = This->base.resource;
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci    DBG("This=%p lod=%u last_level=%u\n", This,
423bf215546Sopenharmony_ci        This->managed.lod, This->base.info.last_level);
424bf215546Sopenharmony_ci
425bf215546Sopenharmony_ci    assert(This->base.pool == D3DPOOL_MANAGED);
426bf215546Sopenharmony_ci
427bf215546Sopenharmony_ci    templ = This->base.info;
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci    if (This->managed.lod) {
430bf215546Sopenharmony_ci        templ.width0 = u_minify(templ.width0, This->managed.lod);
431bf215546Sopenharmony_ci        templ.height0 = u_minify(templ.height0, This->managed.lod);
432bf215546Sopenharmony_ci        templ.depth0 = u_minify(templ.depth0, This->managed.lod);
433bf215546Sopenharmony_ci    }
434bf215546Sopenharmony_ci    templ.last_level = This->base.info.last_level - This->managed.lod;
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci    if (old) {
437bf215546Sopenharmony_ci        /* LOD might have changed. */
438bf215546Sopenharmony_ci        if (old->width0 == templ.width0 &&
439bf215546Sopenharmony_ci            old->height0 == templ.height0 &&
440bf215546Sopenharmony_ci            old->depth0 == templ.depth0)
441bf215546Sopenharmony_ci            return D3D_OK;
442bf215546Sopenharmony_ci    }
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci    res = nine_resource_create_with_retry(This->base.base.device, screen, &templ);
445bf215546Sopenharmony_ci    if (!res)
446bf215546Sopenharmony_ci        return D3DERR_OUTOFVIDEOMEMORY;
447bf215546Sopenharmony_ci    This->base.resource = res;
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci    if (old && CopyData) { /* Don't return without releasing old ! */
450bf215546Sopenharmony_ci        struct pipe_box box;
451bf215546Sopenharmony_ci        box.x = 0;
452bf215546Sopenharmony_ci        box.y = 0;
453bf215546Sopenharmony_ci        box.z = 0;
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_ci        l = (This->managed.lod < This->managed.lod_resident) ? This->managed.lod_resident - This->managed.lod : 0;
456bf215546Sopenharmony_ci        m = (This->managed.lod < This->managed.lod_resident) ? 0 : This->managed.lod - This->managed.lod_resident;
457bf215546Sopenharmony_ci
458bf215546Sopenharmony_ci        box.width = u_minify(templ.width0, l);
459bf215546Sopenharmony_ci        box.height = u_minify(templ.height0, l);
460bf215546Sopenharmony_ci        box.depth = u_minify(templ.depth0, l);
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci        pipe = nine_context_get_pipe_acquire(This->base.base.device);
463bf215546Sopenharmony_ci
464bf215546Sopenharmony_ci        for (; l <= templ.last_level; ++l, ++m) {
465bf215546Sopenharmony_ci            pipe->resource_copy_region(pipe,
466bf215546Sopenharmony_ci                                       res, l, 0, 0, 0,
467bf215546Sopenharmony_ci                                       old, m, &box);
468bf215546Sopenharmony_ci            box.width = u_minify(box.width, 1);
469bf215546Sopenharmony_ci            box.height = u_minify(box.height, 1);
470bf215546Sopenharmony_ci            box.depth = u_minify(box.depth, 1);
471bf215546Sopenharmony_ci        }
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci        nine_context_get_pipe_release(This->base.base.device);
474bf215546Sopenharmony_ci    }
475bf215546Sopenharmony_ci    pipe_resource_reference(&old, NULL);
476bf215546Sopenharmony_ci
477bf215546Sopenharmony_ci    return D3D_OK;
478bf215546Sopenharmony_ci}
479bf215546Sopenharmony_ci
480bf215546Sopenharmony_ci#define SWIZZLE_TO_REPLACE(s) (s == PIPE_SWIZZLE_0 || \
481bf215546Sopenharmony_ci                               s == PIPE_SWIZZLE_1 || \
482bf215546Sopenharmony_ci                               s == PIPE_SWIZZLE_NONE)
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ciHRESULT
485bf215546Sopenharmony_ciNineBaseTexture9_UpdateSamplerView( struct NineBaseTexture9 *This,
486bf215546Sopenharmony_ci                                    const int sRGB )
487bf215546Sopenharmony_ci{
488bf215546Sopenharmony_ci    const struct util_format_description *desc;
489bf215546Sopenharmony_ci    struct pipe_context *pipe;
490bf215546Sopenharmony_ci    struct pipe_screen *screen = NineDevice9_GetScreen(This->base.base.device);
491bf215546Sopenharmony_ci    struct pipe_resource *resource = This->base.resource;
492bf215546Sopenharmony_ci    struct pipe_sampler_view templ;
493bf215546Sopenharmony_ci    enum pipe_format srgb_format;
494bf215546Sopenharmony_ci    unsigned i;
495bf215546Sopenharmony_ci    uint8_t swizzle[4];
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci    DBG("This=%p sRGB=%d\n", This, sRGB);
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_ci    if (unlikely(!resource)) {
500bf215546Sopenharmony_ci	if (unlikely(This->format == D3DFMT_NULL))
501bf215546Sopenharmony_ci            return D3D_OK;
502bf215546Sopenharmony_ci        NineBaseTexture9_Dump(This);
503bf215546Sopenharmony_ci    }
504bf215546Sopenharmony_ci    assert(resource);
505bf215546Sopenharmony_ci
506bf215546Sopenharmony_ci    pipe_sampler_view_reference(&This->view[sRGB], NULL);
507bf215546Sopenharmony_ci
508bf215546Sopenharmony_ci    swizzle[0] = PIPE_SWIZZLE_X;
509bf215546Sopenharmony_ci    swizzle[1] = PIPE_SWIZZLE_Y;
510bf215546Sopenharmony_ci    swizzle[2] = PIPE_SWIZZLE_Z;
511bf215546Sopenharmony_ci    swizzle[3] = PIPE_SWIZZLE_W;
512bf215546Sopenharmony_ci    desc = util_format_description(resource->format);
513bf215546Sopenharmony_ci    if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
514bf215546Sopenharmony_ci        /* msdn doc is incomplete here and wrong.
515bf215546Sopenharmony_ci         * The only formats that can be read directly here
516bf215546Sopenharmony_ci         * are DF16, DF24 and INTZ.
517bf215546Sopenharmony_ci         * Tested on win the swizzle is
518bf215546Sopenharmony_ci         * R = depth, G = B = 0, A = 1 for DF16 and DF24
519bf215546Sopenharmony_ci         * R = G = B = A = depth for INTZ
520bf215546Sopenharmony_ci         * For the other ZS formats that can't be read directly
521bf215546Sopenharmony_ci         * but can be used as shadow map, the result is duplicated on
522bf215546Sopenharmony_ci         * all channel */
523bf215546Sopenharmony_ci        if (This->format == D3DFMT_DF16 ||
524bf215546Sopenharmony_ci            This->format == D3DFMT_DF24) {
525bf215546Sopenharmony_ci            swizzle[1] = PIPE_SWIZZLE_0;
526bf215546Sopenharmony_ci            swizzle[2] = PIPE_SWIZZLE_0;
527bf215546Sopenharmony_ci            swizzle[3] = PIPE_SWIZZLE_1;
528bf215546Sopenharmony_ci        } else {
529bf215546Sopenharmony_ci            swizzle[1] = PIPE_SWIZZLE_X;
530bf215546Sopenharmony_ci            swizzle[2] = PIPE_SWIZZLE_X;
531bf215546Sopenharmony_ci            swizzle[3] = PIPE_SWIZZLE_X;
532bf215546Sopenharmony_ci        }
533bf215546Sopenharmony_ci    } else if (resource->format == PIPE_FORMAT_RGTC2_UNORM) {
534bf215546Sopenharmony_ci        swizzle[0] = PIPE_SWIZZLE_Y;
535bf215546Sopenharmony_ci        swizzle[1] = PIPE_SWIZZLE_X;
536bf215546Sopenharmony_ci        swizzle[2] = PIPE_SWIZZLE_1;
537bf215546Sopenharmony_ci        swizzle[3] = PIPE_SWIZZLE_1;
538bf215546Sopenharmony_ci    } else if (resource->format != PIPE_FORMAT_A8_UNORM &&
539bf215546Sopenharmony_ci               resource->format != PIPE_FORMAT_RGTC1_UNORM) {
540bf215546Sopenharmony_ci        /* exceptions:
541bf215546Sopenharmony_ci         * A8 should have 0.0 as default values for RGB.
542bf215546Sopenharmony_ci         * ATI1/RGTC1 should be r 0 0 1 (tested on windows).
543bf215546Sopenharmony_ci         * It is already what gallium does. All the other ones
544bf215546Sopenharmony_ci         * should have 1.0 for non-defined values */
545bf215546Sopenharmony_ci        for (i = 0; i < 4; i++) {
546bf215546Sopenharmony_ci            if (SWIZZLE_TO_REPLACE(desc->swizzle[i]))
547bf215546Sopenharmony_ci                swizzle[i] = PIPE_SWIZZLE_1;
548bf215546Sopenharmony_ci        }
549bf215546Sopenharmony_ci    }
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci    /* if requested and supported, convert to the sRGB format */
552bf215546Sopenharmony_ci    srgb_format = util_format_srgb(resource->format);
553bf215546Sopenharmony_ci    if (sRGB && srgb_format != PIPE_FORMAT_NONE &&
554bf215546Sopenharmony_ci        screen->is_format_supported(screen, srgb_format,
555bf215546Sopenharmony_ci                                    resource->target, 0, 0, resource->bind))
556bf215546Sopenharmony_ci        templ.format = srgb_format;
557bf215546Sopenharmony_ci    else
558bf215546Sopenharmony_ci        templ.format = resource->format;
559bf215546Sopenharmony_ci    templ.u.tex.first_layer = 0;
560bf215546Sopenharmony_ci    templ.u.tex.last_layer = resource->target == PIPE_TEXTURE_3D ?
561bf215546Sopenharmony_ci                             0 : resource->array_size - 1;
562bf215546Sopenharmony_ci    templ.u.tex.first_level = 0;
563bf215546Sopenharmony_ci    templ.u.tex.last_level = resource->last_level;
564bf215546Sopenharmony_ci    templ.swizzle_r = swizzle[0];
565bf215546Sopenharmony_ci    templ.swizzle_g = swizzle[1];
566bf215546Sopenharmony_ci    templ.swizzle_b = swizzle[2];
567bf215546Sopenharmony_ci    templ.swizzle_a = swizzle[3];
568bf215546Sopenharmony_ci    templ.target = resource->target;
569bf215546Sopenharmony_ci
570bf215546Sopenharmony_ci    pipe = nine_context_get_pipe_acquire(This->base.base.device);
571bf215546Sopenharmony_ci    This->view[sRGB] = pipe->create_sampler_view(pipe, resource, &templ);
572bf215546Sopenharmony_ci    nine_context_get_pipe_release(This->base.base.device);
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci    DBG("sampler view = %p(resource = %p)\n", This->view[sRGB], resource);
575bf215546Sopenharmony_ci
576bf215546Sopenharmony_ci    return This->view[sRGB] ? D3D_OK : D3DERR_DRIVERINTERNALERROR;
577bf215546Sopenharmony_ci}
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_civoid NINE_WINAPI
580bf215546Sopenharmony_ciNineBaseTexture9_PreLoad( struct NineBaseTexture9 *This )
581bf215546Sopenharmony_ci{
582bf215546Sopenharmony_ci    DBG("This=%p\n", This);
583bf215546Sopenharmony_ci
584bf215546Sopenharmony_ci    if (This->base.pool == D3DPOOL_MANAGED)
585bf215546Sopenharmony_ci        NineBaseTexture9_UploadSelf(This);
586bf215546Sopenharmony_ci}
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_civoid
589bf215546Sopenharmony_ciNineBaseTexture9_UnLoad( struct NineBaseTexture9 *This )
590bf215546Sopenharmony_ci{
591bf215546Sopenharmony_ci    DBG("This=%p\n", This);
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci    if (This->base.pool != D3DPOOL_MANAGED ||
594bf215546Sopenharmony_ci        This->managed.lod_resident == -1)
595bf215546Sopenharmony_ci        return;
596bf215546Sopenharmony_ci
597bf215546Sopenharmony_ci    DBG("This=%p, releasing resource\n", This);
598bf215546Sopenharmony_ci    pipe_resource_reference(&This->base.resource, NULL);
599bf215546Sopenharmony_ci    This->managed.lod_resident = -1;
600bf215546Sopenharmony_ci    This->managed.dirty = TRUE;
601bf215546Sopenharmony_ci
602bf215546Sopenharmony_ci    /* If the texture is bound, we have to re-upload it */
603bf215546Sopenharmony_ci    BASETEX_REGISTER_UPDATE(This);
604bf215546Sopenharmony_ci}
605bf215546Sopenharmony_ci
606bf215546Sopenharmony_ci#if defined(DEBUG) || !defined(NDEBUG)
607bf215546Sopenharmony_civoid
608bf215546Sopenharmony_ciNineBaseTexture9_Dump( struct NineBaseTexture9 *This )
609bf215546Sopenharmony_ci{
610bf215546Sopenharmony_ci    DBG("\nNineBaseTexture9(%p->NULL/%p): Pool=%s Type=%s Usage=%s\n"
611bf215546Sopenharmony_ci        "Format=%s Dims=%ux%ux%u/%u LastLevel=%u Lod=%u(%u)\n", This,
612bf215546Sopenharmony_ci        This->base.resource,
613bf215546Sopenharmony_ci        nine_D3DPOOL_to_str(This->base.pool),
614bf215546Sopenharmony_ci        nine_D3DRTYPE_to_str(This->base.type),
615bf215546Sopenharmony_ci        nine_D3DUSAGE_to_str(This->base.usage),
616bf215546Sopenharmony_ci        d3dformat_to_string(This->format),
617bf215546Sopenharmony_ci        This->base.info.width0, This->base.info.height0, This->base.info.depth0,
618bf215546Sopenharmony_ci        This->base.info.array_size, This->base.info.last_level,
619bf215546Sopenharmony_ci        This->managed.lod, This->managed.lod_resident);
620bf215546Sopenharmony_ci}
621bf215546Sopenharmony_ci#endif /* DEBUG || !NDEBUG */
622