1bf215546Sopenharmony_ci/**********************************************************
2bf215546Sopenharmony_ci * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person
5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation
6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without
7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy,
8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies
9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is
10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be
13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22bf215546Sopenharmony_ci * SOFTWARE.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci **********************************************************/
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "svga_cmd.h"
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "pipe/p_state.h"
29bf215546Sopenharmony_ci#include "pipe/p_defines.h"
30bf215546Sopenharmony_ci#include "util/u_inlines.h"
31bf215546Sopenharmony_ci#include "os/os_thread.h"
32bf215546Sopenharmony_ci#include "util/format/u_format.h"
33bf215546Sopenharmony_ci#include "util/u_math.h"
34bf215546Sopenharmony_ci#include "util/u_memory.h"
35bf215546Sopenharmony_ci#include "util/u_string.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci#include "svga_format.h"
38bf215546Sopenharmony_ci#include "svga_screen.h"
39bf215546Sopenharmony_ci#include "svga_context.h"
40bf215546Sopenharmony_ci#include "svga_resource_texture.h"
41bf215546Sopenharmony_ci#include "svga_sampler_view.h"
42bf215546Sopenharmony_ci#include "svga_debug.h"
43bf215546Sopenharmony_ci#include "svga_surface.h"
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_civoid
47bf215546Sopenharmony_cisvga_debug_describe_sampler_view(char *buf, const struct svga_sampler_view *sv)
48bf215546Sopenharmony_ci{
49bf215546Sopenharmony_ci   char res[128];
50bf215546Sopenharmony_ci   debug_describe_resource(res, sv->texture);
51bf215546Sopenharmony_ci   sprintf(buf, "svga_sampler_view<%s,[%u,%u]>",
52bf215546Sopenharmony_ci                res, sv->min_lod, sv->max_lod);
53bf215546Sopenharmony_ci}
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_cistruct svga_sampler_view *
57bf215546Sopenharmony_cisvga_get_tex_sampler_view(struct pipe_context *pipe,
58bf215546Sopenharmony_ci			  struct pipe_resource *pt,
59bf215546Sopenharmony_ci                          unsigned min_lod, unsigned max_lod)
60bf215546Sopenharmony_ci{
61bf215546Sopenharmony_ci   struct svga_context *svga = svga_context(pipe);
62bf215546Sopenharmony_ci   struct svga_screen *ss = svga_screen(pipe->screen);
63bf215546Sopenharmony_ci   struct svga_texture *tex = svga_texture(pt);
64bf215546Sopenharmony_ci   struct svga_sampler_view *sv = NULL;
65bf215546Sopenharmony_ci   SVGA3dSurface1Flags flags = SVGA3D_SURFACE_HINT_TEXTURE;
66bf215546Sopenharmony_ci   SVGA3dSurfaceFormat format = svga_translate_format(ss, pt->format,
67bf215546Sopenharmony_ci                                                      PIPE_BIND_SAMPLER_VIEW);
68bf215546Sopenharmony_ci   boolean view = TRUE;
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci   assert(pt);
71bf215546Sopenharmony_ci   assert(min_lod <= max_lod);
72bf215546Sopenharmony_ci   assert(max_lod <= pt->last_level);
73bf215546Sopenharmony_ci   assert(!svga_have_vgpu10(svga));
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   /* Is a view needed */
76bf215546Sopenharmony_ci   {
77bf215546Sopenharmony_ci      /*
78bf215546Sopenharmony_ci       * Can't control max lod. For first level views and when we only
79bf215546Sopenharmony_ci       * look at one level we disable mip filtering to achive the same
80bf215546Sopenharmony_ci       * results as a view.
81bf215546Sopenharmony_ci       */
82bf215546Sopenharmony_ci      if (min_lod == 0 && max_lod >= pt->last_level)
83bf215546Sopenharmony_ci         view = FALSE;
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci      if (ss->debug.no_sampler_view)
86bf215546Sopenharmony_ci         view = FALSE;
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci      if (ss->debug.force_sampler_view)
89bf215546Sopenharmony_ci         view = TRUE;
90bf215546Sopenharmony_ci   }
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci   /* First try the cache */
93bf215546Sopenharmony_ci   if (view) {
94bf215546Sopenharmony_ci      mtx_lock(&ss->tex_mutex);
95bf215546Sopenharmony_ci      if (tex->cached_view &&
96bf215546Sopenharmony_ci          tex->cached_view->min_lod == min_lod &&
97bf215546Sopenharmony_ci          tex->cached_view->max_lod == max_lod) {
98bf215546Sopenharmony_ci         svga_sampler_view_reference(&sv, tex->cached_view);
99bf215546Sopenharmony_ci         mtx_unlock(&ss->tex_mutex);
100bf215546Sopenharmony_ci         SVGA_DBG(DEBUG_VIEWS, "svga: Sampler view: reuse %p, %u %u, last %u\n",
101bf215546Sopenharmony_ci                              pt, min_lod, max_lod, pt->last_level);
102bf215546Sopenharmony_ci         svga_validate_sampler_view(svga_context(pipe), sv);
103bf215546Sopenharmony_ci         return sv;
104bf215546Sopenharmony_ci      }
105bf215546Sopenharmony_ci      mtx_unlock(&ss->tex_mutex);
106bf215546Sopenharmony_ci   }
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci   sv = CALLOC_STRUCT(svga_sampler_view);
109bf215546Sopenharmony_ci   if (!sv)
110bf215546Sopenharmony_ci      return NULL;
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci   pipe_reference_init(&sv->reference, 1);
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci   /* Note: we're not refcounting the texture resource here to avoid
115bf215546Sopenharmony_ci    * a circular dependency.
116bf215546Sopenharmony_ci    */
117bf215546Sopenharmony_ci   sv->texture = pt;
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci   sv->min_lod = min_lod;
120bf215546Sopenharmony_ci   sv->max_lod = max_lod;
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   /* No view needed just use the whole texture */
123bf215546Sopenharmony_ci   if (!view) {
124bf215546Sopenharmony_ci      SVGA_DBG(DEBUG_VIEWS,
125bf215546Sopenharmony_ci               "svga: Sampler view: no %p, mips %u..%u, nr %u, size (%ux%ux%u), last %u\n",
126bf215546Sopenharmony_ci               pt, min_lod, max_lod,
127bf215546Sopenharmony_ci               max_lod - min_lod + 1,
128bf215546Sopenharmony_ci               pt->width0,
129bf215546Sopenharmony_ci               pt->height0,
130bf215546Sopenharmony_ci               pt->depth0,
131bf215546Sopenharmony_ci               pt->last_level);
132bf215546Sopenharmony_ci      sv->key.cachable = 0;
133bf215546Sopenharmony_ci      sv->handle = tex->handle;
134bf215546Sopenharmony_ci      debug_reference(&sv->reference,
135bf215546Sopenharmony_ci                      (debug_reference_descriptor)svga_debug_describe_sampler_view, 0);
136bf215546Sopenharmony_ci      return sv;
137bf215546Sopenharmony_ci   }
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ci   SVGA_DBG(DEBUG_VIEWS,
140bf215546Sopenharmony_ci            "svga: Sampler view: yes %p, mips %u..%u, nr %u, size (%ux%ux%u), last %u\n",
141bf215546Sopenharmony_ci            pt, min_lod, max_lod,
142bf215546Sopenharmony_ci            max_lod - min_lod + 1,
143bf215546Sopenharmony_ci            pt->width0,
144bf215546Sopenharmony_ci            pt->height0,
145bf215546Sopenharmony_ci            pt->depth0,
146bf215546Sopenharmony_ci            pt->last_level);
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci   sv->age = tex->age;
149bf215546Sopenharmony_ci   sv->handle = svga_texture_view_surface(svga, tex,
150bf215546Sopenharmony_ci                                          PIPE_BIND_SAMPLER_VIEW,
151bf215546Sopenharmony_ci                                          flags, format,
152bf215546Sopenharmony_ci                                          min_lod,
153bf215546Sopenharmony_ci                                          max_lod - min_lod + 1,
154bf215546Sopenharmony_ci                                          -1, 1, -1, FALSE,
155bf215546Sopenharmony_ci                                          &sv->key);
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   if (!sv->handle) {
158bf215546Sopenharmony_ci      sv->key.cachable = 0;
159bf215546Sopenharmony_ci      sv->handle = tex->handle;
160bf215546Sopenharmony_ci      debug_reference(&sv->reference,
161bf215546Sopenharmony_ci                      (debug_reference_descriptor)
162bf215546Sopenharmony_ci                      svga_debug_describe_sampler_view, 0);
163bf215546Sopenharmony_ci      return sv;
164bf215546Sopenharmony_ci   }
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   mtx_lock(&ss->tex_mutex);
167bf215546Sopenharmony_ci   svga_sampler_view_reference(&tex->cached_view, sv);
168bf215546Sopenharmony_ci   mtx_unlock(&ss->tex_mutex);
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci   debug_reference(&sv->reference,
171bf215546Sopenharmony_ci                   (debug_reference_descriptor)
172bf215546Sopenharmony_ci                   svga_debug_describe_sampler_view, 0);
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci   return sv;
175bf215546Sopenharmony_ci}
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_civoid
179bf215546Sopenharmony_cisvga_validate_sampler_view(struct svga_context *svga,
180bf215546Sopenharmony_ci                           struct svga_sampler_view *v)
181bf215546Sopenharmony_ci{
182bf215546Sopenharmony_ci   struct svga_texture *tex = svga_texture(v->texture);
183bf215546Sopenharmony_ci   unsigned numFaces;
184bf215546Sopenharmony_ci   unsigned age = 0;
185bf215546Sopenharmony_ci   int i;
186bf215546Sopenharmony_ci   unsigned k;
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci   assert(svga);
189bf215546Sopenharmony_ci   assert(!svga_have_vgpu10(svga));
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci   if (v->handle == tex->handle)
192bf215546Sopenharmony_ci      return;
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   age = tex->age;
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci   if (tex->b.target == PIPE_TEXTURE_CUBE)
197bf215546Sopenharmony_ci      numFaces = 6;
198bf215546Sopenharmony_ci   else
199bf215546Sopenharmony_ci      numFaces = 1;
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   for (i = v->min_lod; i <= v->max_lod; i++) {
202bf215546Sopenharmony_ci      for (k = 0; k < numFaces; k++) {
203bf215546Sopenharmony_ci         assert(i < ARRAY_SIZE(tex->view_age));
204bf215546Sopenharmony_ci         if (v->age < tex->view_age[i])
205bf215546Sopenharmony_ci            svga_texture_copy_handle(svga,
206bf215546Sopenharmony_ci                                     tex->handle, 0, 0, 0, i, k,
207bf215546Sopenharmony_ci                                     v->handle, 0, 0, 0, i - v->min_lod, k,
208bf215546Sopenharmony_ci                                     u_minify(tex->b.width0, i),
209bf215546Sopenharmony_ci                                     u_minify(tex->b.height0, i),
210bf215546Sopenharmony_ci                                     u_minify(tex->b.depth0, i));
211bf215546Sopenharmony_ci      }
212bf215546Sopenharmony_ci   }
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci   v->age = age;
215bf215546Sopenharmony_ci}
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_civoid
219bf215546Sopenharmony_cisvga_destroy_sampler_view_priv(struct svga_sampler_view *v)
220bf215546Sopenharmony_ci{
221bf215546Sopenharmony_ci   struct svga_texture *tex = svga_texture(v->texture);
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci   if (v->handle != tex->handle) {
224bf215546Sopenharmony_ci      struct svga_screen *ss = svga_screen(v->texture->screen);
225bf215546Sopenharmony_ci      SVGA_DBG(DEBUG_DMA, "unref sid %p (sampler view)\n", v->handle);
226bf215546Sopenharmony_ci      svga_screen_surface_destroy(ss, &v->key,
227bf215546Sopenharmony_ci                                  svga_was_texture_rendered_to(tex),
228bf215546Sopenharmony_ci                                  &v->handle);
229bf215546Sopenharmony_ci   }
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci   /* Note: we're not refcounting the texture resource here to avoid
232bf215546Sopenharmony_ci    * a circular dependency.
233bf215546Sopenharmony_ci    */
234bf215546Sopenharmony_ci   v->texture = NULL;
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci   FREE(v);
237bf215546Sopenharmony_ci}
238