xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/nouveau/nv30/nv30_clear.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2012 Red Hat Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: Ben Skeggs
23  *
24  */
25 
26 #include "pipe/p_defines.h"
27 #include "util/u_pack_color.h"
28 
29 #include "nouveau_gldefs.h"
30 #include "nv_object.xml.h"
31 #include "nv30/nv30-40_3d.xml.h"
32 #include "nv30/nv30_context.h"
33 #include "nv30/nv30_winsys.h"
34 #include "nv30/nv30_format.h"
35 
36 static inline uint32_t
pack_rgba(enum pipe_format format,const float * rgba)37 pack_rgba(enum pipe_format format, const float *rgba)
38 {
39    union util_color uc;
40    util_pack_color(rgba, format, &uc);
41    return uc.ui[0];
42 }
43 
44 static inline uint32_t
pack_zeta(enum pipe_format format,double depth,unsigned stencil)45 pack_zeta(enum pipe_format format, double depth, unsigned stencil)
46 {
47    uint32_t zuint = (uint32_t)(depth * 4294967295.0);
48    if (format != PIPE_FORMAT_Z16_UNORM)
49       return (zuint & 0xffffff00) | (stencil & 0xff);
50    return zuint >> 16;
51 }
52 
53 static void
nv30_clear(struct pipe_context * pipe,unsigned buffers,const struct pipe_scissor_state * scissor_state,const union pipe_color_union * color,double depth,unsigned stencil)54 nv30_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state,
55            const union pipe_color_union *color, double depth, unsigned stencil)
56 {
57    struct nv30_context *nv30 = nv30_context(pipe);
58    struct nouveau_pushbuf *push = nv30->base.pushbuf;
59    struct pipe_framebuffer_state *fb = &nv30->framebuffer;
60    uint32_t colr = 0, zeta = 0, mode = 0;
61 
62    if (!nv30_state_validate(nv30, NV30_NEW_FRAMEBUFFER, true))
63       return;
64 
65    if (scissor_state) {
66       uint32_t minx = scissor_state->minx;
67       uint32_t maxx = MIN2(fb->width, scissor_state->maxx);
68       uint32_t miny = scissor_state->miny;
69       uint32_t maxy = MIN2(fb->height, scissor_state->maxy);
70 
71       BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
72       PUSH_DATA (push, minx | (maxx - minx) << 16);
73       PUSH_DATA (push, miny | (maxy - miny) << 16);
74    }
75    else {
76       BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
77       PUSH_DATA (push, 0x10000000);
78       PUSH_DATA (push, 0x10000000);
79    }
80 
81    if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
82       colr  = pack_rgba(fb->cbufs[0]->format, color->f);
83       mode |= NV30_3D_CLEAR_BUFFERS_COLOR_R |
84               NV30_3D_CLEAR_BUFFERS_COLOR_G |
85               NV30_3D_CLEAR_BUFFERS_COLOR_B |
86               NV30_3D_CLEAR_BUFFERS_COLOR_A;
87    }
88 
89    if (fb->zsbuf) {
90       zeta = pack_zeta(fb->zsbuf->format, depth, stencil);
91       if (buffers & PIPE_CLEAR_DEPTH)
92          mode |= NV30_3D_CLEAR_BUFFERS_DEPTH;
93       if (buffers & PIPE_CLEAR_STENCIL) {
94          mode |= NV30_3D_CLEAR_BUFFERS_STENCIL;
95          BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(0)), 2);
96          PUSH_DATA (push, 0);
97          PUSH_DATA (push, 0x000000ff);
98          nv30->dirty |= NV30_NEW_ZSA;
99       }
100    }
101 
102    /*XXX: wtf? fixes clears sometimes not clearing on nv3x... */
103    if (nv30->screen->eng3d->oclass < NV40_3D_CLASS) {
104       BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3);
105       PUSH_DATA (push, zeta);
106       PUSH_DATA (push, colr);
107       PUSH_DATA (push, mode);
108    }
109 
110    BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3);
111    PUSH_DATA (push, zeta);
112    PUSH_DATA (push, colr);
113    PUSH_DATA (push, mode);
114 
115    nv30_state_release(nv30);
116 
117    /* Make sure regular draw commands will get their scissor state set */
118    nv30->dirty |= NV30_NEW_SCISSOR;
119    nv30->state.scissor_off = 0;
120 }
121 
122 static void
nv30_clear_render_target(struct pipe_context * pipe,struct pipe_surface * ps,const union pipe_color_union * color,unsigned x,unsigned y,unsigned w,unsigned h,bool render_condition_enabled)123 nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps,
124                          const union pipe_color_union *color,
125                          unsigned x, unsigned y, unsigned w, unsigned h,
126                          bool render_condition_enabled)
127 {
128    struct nv30_context *nv30 = nv30_context(pipe);
129    struct nv30_surface *sf = nv30_surface(ps);
130    struct nv30_miptree *mt = nv30_miptree(ps->texture);
131    struct nouveau_pushbuf *push = nv30->base.pushbuf;
132    struct nouveau_object *eng3d = nv30->screen->eng3d;
133    uint32_t rt_format;
134 
135    rt_format = nv30_format(pipe->screen, ps->format)->hw;
136    if (util_format_get_blocksize(ps->format) == 4)
137       rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8;
138    else
139       rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16;
140 
141    if (nv30_miptree(ps->texture)->swizzled) {
142       rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
143       rt_format |= util_logbase2(sf->width) << 16;
144       rt_format |= util_logbase2(sf->height) << 24;
145    } else {
146       rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
147    }
148 
149    if (!PUSH_SPACE_EX(push, 32, 1, 0) ||
150        PUSH_REF1(push, mt->base.bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR))
151       return;
152 
153    BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
154    PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0);
155    BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
156    PUSH_DATA (push, sf->width << 16);
157    PUSH_DATA (push, sf->height << 16);
158    PUSH_DATA (push, rt_format);
159    BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 2);
160    if (eng3d->oclass < NV40_3D_CLASS)
161       PUSH_DATA (push, (sf->pitch << 16) | sf->pitch);
162    else
163       PUSH_DATA (push, sf->pitch);
164    PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0);
165    BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
166    PUSH_DATA (push, (w << 16) | x);
167    PUSH_DATA (push, (h << 16) | y);
168 
169    BEGIN_NV04(push, NV30_3D(CLEAR_COLOR_VALUE), 2);
170    PUSH_DATA (push, pack_rgba(ps->format, color->f));
171    PUSH_DATA (push, NV30_3D_CLEAR_BUFFERS_COLOR_R |
172                     NV30_3D_CLEAR_BUFFERS_COLOR_G |
173                     NV30_3D_CLEAR_BUFFERS_COLOR_B |
174                     NV30_3D_CLEAR_BUFFERS_COLOR_A);
175 
176    nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR;
177    nv30->state.scissor_off = 0;
178 }
179 
180 static void
nv30_clear_depth_stencil(struct pipe_context * pipe,struct pipe_surface * ps,unsigned buffers,double depth,unsigned stencil,unsigned x,unsigned y,unsigned w,unsigned h,bool render_condition_enabled)181 nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps,
182                          unsigned buffers, double depth, unsigned stencil,
183                          unsigned x, unsigned y, unsigned w, unsigned h,
184                          bool render_condition_enabled)
185 {
186    struct nv30_context *nv30 = nv30_context(pipe);
187    struct nv30_surface *sf = nv30_surface(ps);
188    struct nv30_miptree *mt = nv30_miptree(ps->texture);
189    struct nouveau_pushbuf *push = nv30->base.pushbuf;
190    struct nouveau_object *eng3d = nv30->screen->eng3d;
191    uint32_t rt_format, mode = 0;
192 
193    rt_format = nv30_format(pipe->screen, ps->format)->hw;
194    if (util_format_get_blocksize(ps->format) == 4)
195       rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8;
196    else
197       rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5;
198 
199    if (nv30_miptree(ps->texture)->swizzled) {
200       rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
201       rt_format |= util_logbase2(sf->width) << 16;
202       rt_format |= util_logbase2(sf->height) << 24;
203    } else {
204       rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
205    }
206 
207    if (buffers & PIPE_CLEAR_DEPTH)
208       mode |= NV30_3D_CLEAR_BUFFERS_DEPTH;
209    if (buffers & PIPE_CLEAR_STENCIL)
210       mode |= NV30_3D_CLEAR_BUFFERS_STENCIL;
211 
212    if (!PUSH_SPACE_EX(push, 32, 1, 0) ||
213        PUSH_REF1(push, mt->base.bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR))
214       return;
215 
216    BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
217    PUSH_DATA (push, 0);
218    BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
219    PUSH_DATA (push, sf->width << 16);
220    PUSH_DATA (push, sf->height << 16);
221    PUSH_DATA (push, rt_format);
222    if (eng3d->oclass < NV40_3D_CLASS) {
223       BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 1);
224       PUSH_DATA (push, (sf->pitch << 16) | sf->pitch);
225    } else {
226       BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1);
227       PUSH_DATA (push, sf->pitch);
228    }
229    BEGIN_NV04(push, NV30_3D(ZETA_OFFSET), 1);
230    PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0);
231    BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
232    PUSH_DATA (push, (w << 16) | x);
233    PUSH_DATA (push, (h << 16) | y);
234 
235    BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 1);
236    PUSH_DATA (push, pack_zeta(ps->format, depth, stencil));
237    BEGIN_NV04(push, NV30_3D(CLEAR_BUFFERS), 1);
238    PUSH_DATA (push, mode);
239 
240    nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR;
241    nv30->state.scissor_off = 0;
242 }
243 
244 void
nv30_clear_init(struct pipe_context * pipe)245 nv30_clear_init(struct pipe_context *pipe)
246 {
247    pipe->clear = nv30_clear;
248    pipe->clear_render_target = nv30_clear_render_target;
249    pipe->clear_depth_stencil = nv30_clear_depth_stencil;
250 }
251