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