1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors:
24bf215546Sopenharmony_ci *    Rob Clark <robclark@freedesktop.org>
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "pipe/p_state.h"
28bf215546Sopenharmony_ci#include "util/u_inlines.h"
29bf215546Sopenharmony_ci#include "util/u_memory.h"
30bf215546Sopenharmony_ci#include "util/u_string.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "freedreno_context.h"
33bf215546Sopenharmony_ci#include "freedreno_resource.h"
34bf215546Sopenharmony_ci#include "freedreno_texture.h"
35bf215546Sopenharmony_ci#include "freedreno_util.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_cistatic void
38bf215546Sopenharmony_cifd_sampler_state_delete(struct pipe_context *pctx, void *hwcso)
39bf215546Sopenharmony_ci{
40bf215546Sopenharmony_ci   FREE(hwcso);
41bf215546Sopenharmony_ci}
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_cistatic void
44bf215546Sopenharmony_cifd_sampler_view_destroy(struct pipe_context *pctx,
45bf215546Sopenharmony_ci                        struct pipe_sampler_view *view)
46bf215546Sopenharmony_ci{
47bf215546Sopenharmony_ci   pipe_resource_reference(&view->texture, NULL);
48bf215546Sopenharmony_ci   FREE(view);
49bf215546Sopenharmony_ci}
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_cistatic void
52bf215546Sopenharmony_cibind_sampler_states(struct fd_texture_stateobj *tex, unsigned start,
53bf215546Sopenharmony_ci                    unsigned nr, void **hwcso)
54bf215546Sopenharmony_ci{
55bf215546Sopenharmony_ci   unsigned i;
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci   for (i = 0; i < nr; i++) {
58bf215546Sopenharmony_ci      unsigned p = i + start;
59bf215546Sopenharmony_ci      tex->samplers[p] = hwcso ? hwcso[i] : NULL;
60bf215546Sopenharmony_ci      if (tex->samplers[p])
61bf215546Sopenharmony_ci         tex->valid_samplers |= (1 << p);
62bf215546Sopenharmony_ci      else
63bf215546Sopenharmony_ci         tex->valid_samplers &= ~(1 << p);
64bf215546Sopenharmony_ci   }
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   tex->num_samplers = util_last_bit(tex->valid_samplers);
67bf215546Sopenharmony_ci}
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_cistatic void
70bf215546Sopenharmony_ciset_sampler_views(struct fd_texture_stateobj *tex, unsigned start, unsigned nr,
71bf215546Sopenharmony_ci                  unsigned unbind_num_trailing_slots, bool take_ownership,
72bf215546Sopenharmony_ci                  struct pipe_sampler_view **views)
73bf215546Sopenharmony_ci{
74bf215546Sopenharmony_ci   unsigned i;
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   for (i = 0; i < nr; i++) {
77bf215546Sopenharmony_ci      struct pipe_sampler_view *view = views ? views[i] : NULL;
78bf215546Sopenharmony_ci      unsigned p = i + start;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci      if (take_ownership) {
81bf215546Sopenharmony_ci         pipe_sampler_view_reference(&tex->textures[p], NULL);
82bf215546Sopenharmony_ci         tex->textures[p] = view;
83bf215546Sopenharmony_ci      } else {
84bf215546Sopenharmony_ci         pipe_sampler_view_reference(&tex->textures[p], view);
85bf215546Sopenharmony_ci      }
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci      if (tex->textures[p]) {
88bf215546Sopenharmony_ci         fd_resource_set_usage(tex->textures[p]->texture, FD_DIRTY_TEX);
89bf215546Sopenharmony_ci         tex->valid_textures |= (1 << p);
90bf215546Sopenharmony_ci      } else {
91bf215546Sopenharmony_ci         tex->valid_textures &= ~(1 << p);
92bf215546Sopenharmony_ci      }
93bf215546Sopenharmony_ci   }
94bf215546Sopenharmony_ci   for (; i < nr + unbind_num_trailing_slots; i++) {
95bf215546Sopenharmony_ci      unsigned p = i + start;
96bf215546Sopenharmony_ci      pipe_sampler_view_reference(&tex->textures[p], NULL);
97bf215546Sopenharmony_ci      tex->valid_textures &= ~(1 << p);
98bf215546Sopenharmony_ci   }
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   tex->num_textures = util_last_bit(tex->valid_textures);
101bf215546Sopenharmony_ci}
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_civoid
104bf215546Sopenharmony_cifd_sampler_states_bind(struct pipe_context *pctx, enum pipe_shader_type shader,
105bf215546Sopenharmony_ci                       unsigned start, unsigned nr, void **hwcso) in_dt
106bf215546Sopenharmony_ci{
107bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   bind_sampler_states(&ctx->tex[shader], start, nr, hwcso);
110bf215546Sopenharmony_ci   fd_context_dirty_shader(ctx, shader, FD_DIRTY_SHADER_TEX);
111bf215546Sopenharmony_ci}
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_civoid
114bf215546Sopenharmony_cifd_set_sampler_views(struct pipe_context *pctx, enum pipe_shader_type shader,
115bf215546Sopenharmony_ci                     unsigned start, unsigned nr,
116bf215546Sopenharmony_ci                     unsigned unbind_num_trailing_slots,
117bf215546Sopenharmony_ci                     bool take_ownership,
118bf215546Sopenharmony_ci                     struct pipe_sampler_view **views) in_dt
119bf215546Sopenharmony_ci{
120bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   set_sampler_views(&ctx->tex[shader], start, nr, unbind_num_trailing_slots,
123bf215546Sopenharmony_ci                     take_ownership, views);
124bf215546Sopenharmony_ci   fd_context_dirty_shader(ctx, shader, FD_DIRTY_SHADER_TEX);
125bf215546Sopenharmony_ci}
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_civoid
128bf215546Sopenharmony_cifd_texture_init(struct pipe_context *pctx)
129bf215546Sopenharmony_ci{
130bf215546Sopenharmony_ci   if (!pctx->delete_sampler_state)
131bf215546Sopenharmony_ci      pctx->delete_sampler_state = fd_sampler_state_delete;
132bf215546Sopenharmony_ci   if (!pctx->sampler_view_destroy)
133bf215546Sopenharmony_ci      pctx->sampler_view_destroy = fd_sampler_view_destroy;
134bf215546Sopenharmony_ci}
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci/* helper for setting up border-color buffer for a3xx/a4xx: */
137bf215546Sopenharmony_civoid
138bf215546Sopenharmony_cifd_setup_border_colors(struct fd_texture_stateobj *tex, void *ptr,
139bf215546Sopenharmony_ci                       unsigned offset)
140bf215546Sopenharmony_ci{
141bf215546Sopenharmony_ci   unsigned i, j;
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci   for (i = 0; i < tex->num_samplers; i++) {
144bf215546Sopenharmony_ci      struct pipe_sampler_state *sampler = tex->samplers[i];
145bf215546Sopenharmony_ci      uint16_t *bcolor =
146bf215546Sopenharmony_ci         (uint16_t *)((uint8_t *)ptr + (BORDERCOLOR_SIZE * offset) +
147bf215546Sopenharmony_ci                      (BORDERCOLOR_SIZE * i));
148bf215546Sopenharmony_ci      uint32_t *bcolor32 = (uint32_t *)&bcolor[16];
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci      if (!sampler)
151bf215546Sopenharmony_ci         continue;
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci      /*
154bf215546Sopenharmony_ci       * XXX HACK ALERT XXX
155bf215546Sopenharmony_ci       *
156bf215546Sopenharmony_ci       * The border colors need to be swizzled in a particular
157bf215546Sopenharmony_ci       * format-dependent order. Even though samplers don't know about
158bf215546Sopenharmony_ci       * formats, we can assume that with a GL state tracker, there's a
159bf215546Sopenharmony_ci       * 1:1 correspondence between sampler and texture. Take advantage
160bf215546Sopenharmony_ci       * of that knowledge.
161bf215546Sopenharmony_ci       */
162bf215546Sopenharmony_ci      if (i < tex->num_textures && tex->textures[i]) {
163bf215546Sopenharmony_ci         const struct util_format_description *desc =
164bf215546Sopenharmony_ci            util_format_description(tex->textures[i]->format);
165bf215546Sopenharmony_ci         for (j = 0; j < 4; j++) {
166bf215546Sopenharmony_ci            if (desc->swizzle[j] >= 4)
167bf215546Sopenharmony_ci               continue;
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci            const struct util_format_channel_description *chan =
170bf215546Sopenharmony_ci               &desc->channel[desc->swizzle[j]];
171bf215546Sopenharmony_ci            uint8_t native = desc->swizzle[j];
172bf215546Sopenharmony_ci            /* Special cases:
173bf215546Sopenharmony_ci             *  - X24S8 is implemented with 8_8_8_8_UINT, so the 'native'
174bf215546Sopenharmony_ci             *    location is actually 0 rather than 1
175bf215546Sopenharmony_ci             *  - X32_S8X24_UINT has stencil with a secretly-S8_UINT resource
176bf215546Sopenharmony_ci             *    so again we want 0 rather than 1
177bf215546Sopenharmony_ci             *
178bf215546Sopenharmony_ci             * In both cases, there is only one non-void format, so we don't
179bf215546Sopenharmony_ci             * have to be too careful.
180bf215546Sopenharmony_ci             *
181bf215546Sopenharmony_ci             * Note that this only affects a4xx -- a3xx did not support
182bf215546Sopenharmony_ci             * stencil texturing, and a5xx+ don't use this helper.
183bf215546Sopenharmony_ci             */
184bf215546Sopenharmony_ci            if (tex->textures[i]->format == PIPE_FORMAT_X24S8_UINT ||
185bf215546Sopenharmony_ci                tex->textures[i]->format == PIPE_FORMAT_X32_S8X24_UINT) {
186bf215546Sopenharmony_ci               native = 0;
187bf215546Sopenharmony_ci            }
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci            if (chan->pure_integer) {
190bf215546Sopenharmony_ci               bcolor32[native + 4] = sampler->border_color.i[j];
191bf215546Sopenharmony_ci               bcolor[native + 8] = sampler->border_color.i[j];
192bf215546Sopenharmony_ci            } else {
193bf215546Sopenharmony_ci               bcolor32[native] = fui(sampler->border_color.f[j]);
194bf215546Sopenharmony_ci               bcolor[native] =
195bf215546Sopenharmony_ci                  _mesa_float_to_half(sampler->border_color.f[j]);
196bf215546Sopenharmony_ci            }
197bf215546Sopenharmony_ci         }
198bf215546Sopenharmony_ci      }
199bf215546Sopenharmony_ci   }
200bf215546Sopenharmony_ci}
201